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 127
| struct Node { int begin; int end; Node() : info(this) {} struct Tag { Tag() {} void apply(const Tag& t) {} } tag; struct Info { Node* node; Info(Node* node = nullptr) : node(node) {} template<class T = Info> Info operator=(const T& info) { return *this; } void apply(const Tag& t) {} Info push(const Info& a, const Info& b) { return *this; } } info; };
struct LazySegmentTree { int n; vector<Node> node; template<class T = Node::Info> LazySegmentTree(const vector<T>& val) { init(val); } template<class T = Node::Info> LazySegmentTree(int n, T v) { init(vector(n, v)); } template<class T = Node::Info> void init(const vector<T>& val) { n = val.size(); node.resize(4 << __lg(n)); function<void(int, int, int)> build = [&](int begin, int end, int p) -> void { this->begin(p) = begin; this->end(p) = end; if (end - begin == 1) { info(p) = val[begin]; return; } int middle = (begin + end) / 2; build(begin, middle, left(p)); build(middle, end, right(p)); push_up(p); }; build(0, n, 1); } int& begin(const int& p) { return node[p].begin; } int& end(const int& p) { return node[p].end; } Node::Tag& tag(const int& p) { return node[p].tag; } Node::Info& info(const int& p) { return node[p].info; } int left(const int& p) const { return p * 2; } int right(const int& p) const { return p * 2 + 1; } void push_up(const int& p) { info(p).push(info(left(p)), info(right(p))); } void apply(const int& p, const Node::Tag& t) { info(p).apply(t); tag(p).apply(t); } void push_down(const int& p) { apply(left(p), tag(p)); apply(right(p), tag(p)); tag(p) = Node::Tag(); } void modify(const int& pos, const Node::Info& i, const int& p = 1) { if (end(p) - begin(p) == 1) { info(p) = i; return; } int middle = (begin(p) + end(p)) / 2; push_down(p); if (pos < middle) { modify(pos, i, left(p)); } else { modify(pos, i, right(p)); } push_up(p); } void rangeApply(const int& l, const int& r, const Node::Tag& t, const int& p = 1) { if (end(p) <= l || r <= begin(p)) { return; } if (l <= begin(p) && end(p) <= r) { return apply(p, t); } push_down(p); rangeApply(l, r, t, left(p)); rangeApply(l, r, t, right(p)); push_up(p); } template<class Error, class Ok> void rangeApply(const int& l, const int& r, const Node::Tag& t, const Error& error, const Ok& ok, const int& p = 1) { if (error(node[p], l, r, t)) { return; } if (ok(node[p], l, r, t)) { return apply(p, t); } push_down(p); rangeApply(l, r, t, error, ok, left(p)); rangeApply(l, r, t, error, ok, right(p)); push_up(p); } Node::Info rangeQuery(const int& l, const int& r, const int& p = 1) { if (end(p) <= l || r <= begin(p)) { return Node::Info(); } if (l <= begin(p) && end(p) <= r) { return info(p); } push_down(p); return Node::Info().push(rangeQuery(l, r, left(p)), rangeQuery(l, r, right(p))); } };
|