7
8
i64 lz; // lz : 区间中所有点,能取到的连通块里的点的最小点权
pair<i64, int> vertix, edge;
9 }tr[N * 4]; // 对每个点 i 维护目前最小的邻接边权(edge.first),以及邻接边权对应的下一
个点(edge.second)
10
11 void push_up(int u) {
12
tr[u].edge = min(tr[u * 2].edge, tr[u * 2 + 1].edge);
tr[u].vertix = min(tr[u * 2].vertix, tr[u * 2 + 1].vertix);
13
14 }
15
16 void build(int u, int l, int r) {
17
tr[u] = {l, r, inf, {a[l], l}, {a[l] + inf, l}};
18
if(l == r) {
19
return ;
20
}
21
int mid = (l + r) / 2;
build(u * 2, l, mid);
build(u * 2 + 1, mid + 1, r);
push_up(u);
22
23
24
25 }
26
27 void push_down(int u) {
28
29
30
31
32
for(auto son : {u * 2, u * 2 + 1}) {
if(tr[son].lz > tr[u].lz) {
tr[son].lz = tr[u].lz;
if(tr[son].vertix.first + tr[u].lz <= tr[son].edge.first) {
tr[son].edge = {tr[son].vertix.first + tr[u].lz,
tr[son].vertix.second};
33
}
34
}
35
}
36 }
37
38 void update(int u, int l, int r, int v) { // 从编号位于[l,r]的点到目前连通块的可
选边,多了一个边权为a[x]+v的,x为区间内的点
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 }
58
if(tr[u].l >= l && tr[u].r <= r) {
if(tr[u].lz <= v) return ;
// cerr << "u : " << u << ", l : " << l
<< ", r : " << r << endl;
tr[u].lz = v;
if(tr[u].vertix.first + v < tr[u].edge.first) {
tr[u].edge = {tr[u].vertix.first + v, tr[u].vertix.second};
}
return ;
}
push_down(u);
int mid = (tr[u].l + tr[u].r) / 2;
if(l <= mid) {
update(u * 2, l, r, v);
}
if(r > mid) {
update(u * 2 + 1, l, r, v);
}
push_up(u);
59 void del(int u, int k) { // 把已经加入连通块的点删掉