maomao90's Library
A C++20 library for competitive programming.
Loading...
Searching...
No Matches
lazy_segtree.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <vector>
5
7
8// Modified from https://judge.yosupo.jp/submission/242469
9
10namespace maomao90 {
11using namespace std;
12
13// 0-indexed
14// left_monoid.merge(right_monoid)
15// new_update.merge(old_update)
16template <Monoid T, Lazy<T> L> struct LazySegTree {
18 explicit LazySegTree(int n) : LazySegTree(vector<T>(n, T::id())) {}
19 explicit LazySegTree(const vector<T> &a) : n(int(a.size())) {
20 size = 1;
21 log = 0;
22 while (size < n) {
23 size <<= 1;
24 log++;
25 }
26 v = vector<T>(2 * size, T::id());
27 lz = vector<L>(size, L::id());
28 for (int i = 0; i < n; i++) {
29 v[size + i] = a[i];
30 }
31 for (int i = size - 1; i >= 1; i--) {
32 update(i);
33 }
34 }
35
36 void set(int p, T x) {
37 assert(0 <= p && p < n);
38 p += size;
39 for (int i = log; i >= 1; i--) {
40 push(p >> i);
41 }
42 v[p] = x;
43 for (int i = 1; i <= log; i++) {
44 update(p >> i);
45 }
46 }
47
48 T get(int p) {
49 assert(0 <= p && p < n);
50 p += size;
51 T res = v[p];
52 for (int i = 1; i <= log; i++) {
53 res = lz[p >> i].apply(res, 1);
54 }
55 return res;
56 }
57
58 // query [l, r) inclusive of left endpoint, exclusive of right endpoint
59 T query(int l, int r) {
60 if (l >= r) {
61 return T::id();
62 }
63 assert(0 <= l && r <= n);
64
65 l += size;
66 r += size;
67
68 int llen = 0, rlen = 0;
69 T sml = T::id(), smr = T::id();
70 int i = 1, l2 = l, r2 = r;
71 for (; l < r; i++, l >>= 1, r >>= 1) {
72 if (l & 1) {
73 sml = sml.merge(v[l++]), llen += 1 << (i - 1);
74 }
75 if (r & 1) {
76 smr = v[--r].merge(smr), rlen += 1 << (i - 1);
77 }
78 if (((l2 >> i) << i) != l2) {
79 sml = lz[l2 >> i].apply(sml, llen);
80 }
81 if (((r2 >> i) << i) != r2) {
82 smr = lz[(r2 - 1) >> i].apply(smr, rlen);
83 }
84 }
85 for (; i <= log; i++) {
86 if (((l2 >> i) << i) != l2) {
87 sml = lz[l2 >> i].apply(sml, llen);
88 }
89 if (((r2 >> i) << i) != r2) {
90 smr = lz[(r2 - 1) >> i].apply(smr, rlen);
91 }
92 }
93 return sml.merge(smr);
94 }
95
96 T all_query() { return v[1]; }
97
98 void update(int p, L f) {
99 assert(0 <= p && p < n);
100 p += size;
101 for (int i = log; i >= 1; i--) {
102 push(p >> i);
103 }
104 v[p] = f.apply(v[p], 1);
105 for (int i = 1; i <= log; i++) {
106 update(p >> i);
107 }
108 }
109
110 // update [l, r) inclusive of left endpoint, exclusive of right endpoint
111 void update(int l, int r, L f) {
112 if (l >= r) {
113 return;
114 }
115 assert(0 <= l && r <= n);
116
117 l += size;
118 r += size;
119
120 for (int i = log; i >= 1; i--) {
121 if (((l >> i) << i) != l) {
122 push(l >> i);
123 }
124 if (((r >> i) << i) != r) {
125 push((r - 1) >> i);
126 }
127 }
128
129 {
130 int l2 = l, r2 = r;
131 while (l < r) {
132 if (l & 1) {
133 all_apply(l++, f);
134 }
135 if (r & 1) {
136 all_apply(--r, f);
137 }
138 l >>= 1;
139 r >>= 1;
140 }
141 l = l2;
142 r = r2;
143 }
144
145 for (int i = 1; i <= log; i++) {
146 if (((l >> i) << i) != l) {
147 update(l >> i);
148 }
149 if (((r >> i) << i) != r) {
150 update((r - 1) >> i);
151 }
152 }
153 }
154
155 template <bool (*pred)(T)> int max_right(int l) {
156 return max_right(l, [](T x) { return pred(x); });
157 }
158
159 // returns largest x such that pred(query(l, x)) is true (note that right
160 // endpoint `x` is exclusive)
161 template <class P> int max_right(int l, P pred) {
162 assert(0 <= l && l <= n);
163 assert(pred(T::id()));
164 if (l == n) {
165 return n;
166 }
167 l += size;
168 for (int i = log; i >= 1; i--) {
169 push(l >> i);
170 }
171 T sm = T::id();
172 do {
173 while (l % 2 == 0) {
174 l >>= 1;
175 }
176 if (!pred(sm.merge(v[l]))) {
177 while (l < size) {
178 push(l);
179 l = (2 * l);
180 if (pred(sm.merge(v[l]))) {
181 sm = sm.merge(v[l]);
182 l++;
183 }
184 }
185 return l - size;
186 }
187 sm = sm.merge(v[l]);
188 l++;
189 } while ((l & -l) != l);
190 return n;
191 }
192
193 template <bool (*pred)(T)> int min_left(int r) {
194 return min_left(r, [](T x) { return pred(x); });
195 }
196 // returns smallest x such that pred(query(x, r)) is true (note that right
197 // endpoint `r` is exlusive)
198 template <class P> int min_left(int r, P pred) {
199 assert(0 <= r && r <= n);
200 if (r == 0) {
201 return 0;
202 }
203 assert(pred(T::id()));
204 r += size;
205 for (int i = log; i >= 1; i--) {
206 push((r - 1) >> i);
207 }
208 T sm = T::id();
209 do {
210 r--;
211 while (r > 1 && (r % 2)) {
212 r >>= 1;
213 }
214 if (!pred(v[r].merge(sm))) {
215 while (r < size) {
216 push(r);
217 r = (2 * r + 1);
218 if (pred(v[r].merge(sm))) {
219 sm = v[r].merge(sm);
220 r--;
221 }
222 }
223 return r + 1 - size;
224 }
225 sm = v[r].merge(sm);
226 } while ((r & -r) != r);
227 return 0;
228 }
229
230private:
231 int n, size, log;
232 vector<T> v;
233 vector<L> lz;
234
235 void update(int k) { v[k] = v[2 * k].merge(v[2 * k + 1]); }
236 void all_apply(int k, L f) {
237 v[k] = f.apply(v[k], 1 << (log - 31 + __builtin_clz(k)));
238 if (k < size) {
239 lz[k] = f.merge(lz[k]);
240 }
241 }
242 void push(int k) {
243 all_apply(2 * k, lz[k]);
244 all_apply(2 * k + 1, lz[k]);
245 lz[k] = L::id();
246 }
247};
248} // namespace maomao90
Definition hashmap.hpp:8
void set(int p, T x)
Definition lazy_segtree.hpp:36
void update(int p, L f)
Definition lazy_segtree.hpp:98
int max_right(int l, P pred)
Definition lazy_segtree.hpp:161
LazySegTree(int n)
Definition lazy_segtree.hpp:18
int max_right(int l)
Definition lazy_segtree.hpp:155
int min_left(int r, P pred)
Definition lazy_segtree.hpp:198
LazySegTree()
Definition lazy_segtree.hpp:17
T all_query()
Definition lazy_segtree.hpp:96
T query(int l, int r)
Definition lazy_segtree.hpp:59
int min_left(int r)
Definition lazy_segtree.hpp:193
void update(int l, int r, L f)
Definition lazy_segtree.hpp:111
T get(int p)
Definition lazy_segtree.hpp:48
LazySegTree(const vector< T > &a)
Definition lazy_segtree.hpp:19