#include #include template class SegmentTree { int n; std::function _update; std::function _merge; std::function _push; void update(int p, int b, int e, int x, int y, U &upd) { if (x <= b && e <= y) { _update(ds[p], upd); } else { int m = (b + e) >> 1, l = p << 1, r = l | 1; _push(ds[p], ds[l], ds[r], b, m, e); if (x < m) update(l, b, m, x, y, upd); if (m < y) update(r, m, e, x, y, upd); ds[p] = _merge(ds[l], ds[r]); } } T query(int p, int b, int e, int x, int y) { if (x <= b && e <= y) { return ds[p]; } else { int m = (b + e) >> 1, l = p << 1, r = l | 1; _push(ds[p], ds[l], ds[r], b, m, e); if (x < m) { auto le = query(l, b, m, x, y); if (m < y) { auto ri = query(r, m, e, x, y); return _merge(le, ri); } else { return le; } } else { return query(r, m, e, x, y); } } } public: std::vector ds; SegmentTree(int n, std::function update, std::function merge, std::function push) : n(n), _update(update), _merge(merge), _push(push) { ds = std::vector(4 * n); } // Update on point void update(int x, U upd) { update(1, 0, n, x, x + 1, upd); } // Update on range void update(int x, int y, U upd) { update(1, 0, n, x, y, upd); } // Query on a point T query(int x) { return query(1, 0, n, x, x + 1); } // Query on a range T query(int x, int y) { return query(1, 0, n, x, y); } }; template void noop_push(T &p, T &l, T &r, int b, int m, int e) {} template class SegmentTreeBuilder { std::function _update; std::function _merge; std::function _push; public: SegmentTreeBuilder() : _push(noop_push) { } SegmentTree *init(int size) { return new SegmentTree(size, _update, _merge, _push); } SegmentTreeBuilder *with_lazy(std::function push) { _push = push; return this; } SegmentTreeBuilder *with_lazy(std::function push) { _push = [push](T &p, T &l, T &r, int b, int m, int e) { push(p, l, r); }; return this; } SegmentTreeBuilder *with_update(std::function update) { _update = update; return this; } SegmentTreeBuilder *with_merge(std::function merge) { _merge = merge; return this; } }; template SegmentTreeBuilder *segment_tree() { return new SegmentTreeBuilder(); } // TODO: Allow custom initializer // TODO: Use array of length 2 * n (instead of 4 * n) // TODO: Use iterative segment tree whenever possible.