SP11470 TTM - To the moon

可持续化线段树的区间加减。

如果用lazy标记的化,发现两个版本的线段树共用的节点不能修改值。

这时候标记永久化就上场了。

标记永久化既不需要下传标记,也不需要通过子节点更新自己。

  • 对于更新,更新一路上的。然后在最底层完全覆盖的节点上打上标记。
  • 对于查询,更新一路的标记,最后加上最底层的值。

注意多思考细节就好了。

代码
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


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
#define mk make_pair
const int N = 1e5 + 10;
const int mod = 1e9 + 7;

int a[N];
struct SustainedTree
{
int scnt;
ll sum[N << 5], tag[N << 5];
int ls[N << 5], rs[N << 5];
void build(int &pos, int l, int r)
{
pos = ++scnt;
if (l == r)
{
sum[pos] = a[l];
return;
}
int mid = (l + r) >> 1;
build(ls[pos], l, mid), build(rs[pos], mid + 1, r);
sum[pos] = sum[ls[pos]] + sum[rs[pos]];
}

void update(int &pos, int pre, int ql, int qr, int v, int l, int r)
{
pos = ++scnt;
sum[pos] = sum[pre], tag[pos] = tag[pre], ls[pos] = ls[pre], rs[pos] = rs[pre];

if (ql <= l && r <= qr)
{
tag[pos] += v;
return;
}

sum[pos] += 1ll * v * (min(qr, r) - max(ql, l) + 1);

int mid = (l + r) >> 1;
if (ql <= mid)
update(ls[pos], ls[pre], ql, qr, v, l, mid);
if (qr > mid)
update(rs[pos], rs[pre], ql, qr, v, mid + 1, r);
}
void query(int pos, int ql, int qr, int l, int r, ll &res)
{
res += 1ll * tag[pos] * (min(qr, r) - max(ql, l) + 1);
if (ql <= l && r <= qr)
{

res += sum[pos];
return;
}
int mid = (l + r) >> 1;
if (ql <= mid)
query(ls[pos], ql, qr, l, mid, res);
if (qr > mid)
query(rs[pos], ql, qr, mid + 1, r, res);
}
} t;

int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + c - '0', c = getchar();
return x * f;
}

int rt[N];
int main()
{
int n = read(), m = read();
for (int i = 1; i <= n; i++)
a[i] = read();
t.build(rt[0], 1, n);
int now = 0;

for (int i = 1; i <= m; i++)
{
char s[5];
scanf("%s", s);
if (s[0] == 'B')
now = read();
else if (s[0] == 'C')
{
int l = read(), r = read(), d = read();
t.update(rt[now + 1], rt[now], l, r, d, 1, n);
now++;
}
else if (s[0] == 'Q')
{
int l = read(), r = read();
ll res = 0;
t.query(rt[now], l, r, 1, n, res);
printf("%lld\n", res);
}
else if (s[0] == 'H')
{
int l = read(), r = read(), z = read();
ll res = 0;
t.query(rt[z], l, r, 1, n, res);
printf("%lld\n", res);
}
}
}