1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include <vector> #include <bit>
using std::bit_width; using std::vector;
template <typename T, typename F> class SegmentTreeLazy { int n;
const int TODO_INIT = 0;
struct Node { T val; F todo; };
vector<Node> tree;
T merge_val(T a, T b) const { return a + b; }
F merge_todo(F todo_a, F todo_b) const { return todo_a + todo_b; }
void maintain(int i) { tree[i].val = merge_val(tree[i << 1].val, tree[(i << 1) + 1].val); }
void apply(int l, int r, int i, F todo) { auto &node = tree[i]; node.val += (r - l + 1) * todo; node.todo = merge_todo(node.todo, todo); }
void spread(int l, int r, int i) { auto &node = tree[i]; if (node.todo == TODO_INIT) { return; } int m = l + ((r - l) >> 1); apply(l, m, i << 1, node.todo); apply(m + 1, r, (i << 1) + 1, node.todo); node.todo = TODO_INIT; }
void build(vector<T> &a, int l, int r, int i) { if (l == r) { tree[i].val = a[l]; return; } int m = l + ((r - l) >> 1); build(a, l, m, i << 1); build(a, m + 1, r, (i << 1) + 1); maintain(i); }
T query(int l, int r, int i, int ql, int qr) { if (ql <= l && r <= qr) { return tree[i].val; } spread(l, r, i); int m = l + ((r - l) >> 1); if (ql > m) { return query(m + 1, r, (i << 1) + 1, ql, qr); } else if (qr < m + 1) { return query(l, m, i << 1, ql, qr); } T l_res = query(l, m, i << 1, ql, qr); T r_res = query(m + 1, r, (i << 1) + 1, ql, qr); return merge_val(l_res, r_res); }
void update(int l, int r, int i, int ql, int qr, F v) { if (ql <= l && r <= qr) { apply(l, r, i, v); return; } spread(l, r, i); int m = l + ((r - l) >> 1); if (ql <= m) { update(l, m, i << 1, ql, qr, v); } if (qr >= m + 1) { update(m + 1, r, (i << 1) + 1, ql, qr, v); } maintain(i); }
public: SegmentTreeLazy(vector<T> &a) : n(a.size()), tree(2 << bit_width(a.size() - 1)) { build(a, 0, n - 1, 1); }
T querySum(int l, int r) { return query(0, n - 1, 1, l, r); }
void add(int l, int r, F v) { update(0, n - 1, 1, l, r, v); } };
|