Segment Tree Lazy 1c016c3d
Recursive segment tree, eager array build, range update with lazy propagation. Default op is range-add + range-min; edit comb()/apply() for another op (see treap-implicit.h for the op-block pattern this follows). T needs operator+, a zero, and to be comparable with numeric_limits.
Time: O(\log n) per operation. tested
content/data-structures/segment-tree-lazy.h
template <typename T>
struct LazySegmentTree {
struct Node {
int l, r;
T val, lazy = T();
Node *left = nullptr, *right = nullptr;
};
T ID() { return numeric_limits<T>::max(); } // op: identity for comb()
T comb(T a, T b) { return min(a, b); } // op: combine two children
void apply(Node *n, T v) { n->val += v; n->lazy += v; } // op: push a lazy tag onto a node
Node *root;
LazySegmentTree(vector<T> &a) { root = build(0, (int)a.size() - 1, a); }
Node *build(int l, int r, vector<T> &a) {
Node *n = new Node();
n->l = l; n->r = r;
if (l == r) { n->val = a[l]; return n; }
int m = (l + r) / 2;
n->left = build(l, m, a);
n->right = build(m + 1, r, a);
n->val = comb(n->left->val, n->right->val);
return n;
}
void push(Node *n) {
if (n->lazy != T()) {
if (n->left) { apply(n->left, n->lazy); apply(n->right, n->lazy); }
n->lazy = T();
}
}
void update(int ul, int ur, T v, Node *n = nullptr) {
if (!n) n = root;
if (ur < n->l || n->r < ul) return;
if (ul <= n->l && n->r <= ur) { apply(n, v); return; }
push(n);
update(ul, ur, v, n->left);
update(ul, ur, v, n->right);
n->val = comb(n->left->val, n->right->val);
}
T query(int ql, int qr, Node *n = nullptr) {
if (!n) n = root;
if (qr < n->l || n->r < ql) return ID();
if (ql <= n->l && n->r <= qr) return n->val;
push(n);
return comb(query(ql, qr, n->left), query(ql, qr, n->right));
}
};