forked from mateusvrs/competitive-programming
-
Notifications
You must be signed in to change notification settings - Fork 0
/
segtreelazy_generic.cpp
116 lines (99 loc) · 2.85 KB
/
segtreelazy_generic.cpp
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
using SegT = ll;
struct QueryT {
SegT mx, mn;
QueryT() : mx(numeric_limits<SegT>::min()), mn(numeric_limits<SegT>::max()) {}
QueryT(SegT _v) : mx(_v), mn(_v) {}
};
inline QueryT combine(QueryT ln, QueryT rn, ii lr1, ii lr2) {
ln.mx = max(ln.mx, rn.mx);
ln.mn = min(ln.mn, rn.mn);
return ln;
}
using LazyT = SegT;
inline QueryT applyLazyInQuery(QueryT q, LazyT l, ii lr) {
if (q.mx == QueryT().mx) q.mx = SegT();
if (q.mn == QueryT().mn) q.mn = SegT();
q.mx += l, q.mn += l;
return q;
}
inline LazyT applyLazyInLazy(LazyT a, LazyT b) { return a + b; }
using UpdateT = SegT;
inline QueryT applyUpdateInQuery(QueryT q, UpdateT u, ii lr) {
if (q.mx == QueryT().mx) q.mx = SegT();
if (q.mn == QueryT().mn) q.mn = SegT();
q.mx += u, q.mn += u;
return q;
}
inline LazyT applyUpdateInLazy(LazyT l, UpdateT u, ii lr) { return l + u; }
template <typename Qt = QueryT, typename Lt = LazyT, typename Ut = UpdateT,
auto C = combine, auto ALQ = applyLazyInQuery,
auto ALL = applyLazyInLazy, auto AUQ = applyUpdateInQuery,
auto AUL = applyUpdateInLazy>
struct LazySegmentTree {
int n, h;
vector<Qt> ts;
vector<Lt> ds;
vector<ii> lrs;
LazySegmentTree(int _n)
: n(_n),
h(sizeof(int) * 8 - __builtin_clz(n)),
ts(n << 1),
ds(n),
lrs(n << 1) {
for (int i = 0; i < n; i++) lrs[i + n] = {i, i};
for (int i = n - 1; i > 0; i--) {
lrs[i] = {lrs[i << 1].first, lrs[i << 1 | 1].second};
}
}
LazySegmentTree(const vector<Qt> &xs) : LazySegmentTree(xs.size()) {
copy(all(xs), ts.begin() + n);
for (int i = 0; i < n; i++) lrs[i + n] = {i, i};
for (int i = n - 1; i > 0; i--) {
ts[i] = C(ts[i << 1], ts[i << 1 | 1], lrs[i << 1], lrs[i << 1 | 1]);
}
}
void set(int p, Qt v) {
ts[p + n] = v;
build(p + n);
}
void upd(int l, int r, Ut v) {
l += n, r += n + 1;
int l0 = l, r0 = r;
for (; l < r; l >>= 1, r >>= 1) {
if (l & 1) apply(l++, v);
if (r & 1) apply(--r, v);
}
build(l0), build(r0 - 1);
}
Qt qry(int l, int r) {
l += n, r += n + 1;
push(l), push(r - 1);
Qt resl = Qt(), resr = Qt();
ii lr1 = {l, l}, lr2 = {r, r};
for (; l < r; l >>= 1, r >>= 1) {
if (l & 1) resl = C(resl, ts[l], lr1, lrs[l]), l++;
if (r & 1) r--, resr = C(ts[r], resr, lrs[r], lr2);
}
return C(resl, resr, lr1, lr2);
}
void build(int p) {
while (p > 1) {
p >>= 1;
ts[p] = ALQ(C(ts[p << 1], ts[p << 1 | 1], lrs[p << 1], lrs[p << 1 | 1]),
ds[p], lrs[p]);
}
}
void push(int p) {
for (int s = h; s > 0; s--) {
int i = p >> s;
if (ds[i] != Lt()) {
apply(i << 1, ds[i]), apply(i << 1 | 1, ds[i]);
ds[i] = Lt();
}
}
}
inline void apply(int p, Ut v) {
ts[p] = AUQ(ts[p], v, lrs[p]);
if (p < n) ds[p] = AUL(ds[p], v, lrs[p]);
}
};