bzoj 4034 2015 haoi t2

文章目錄

BZOJ 4034 HAOI 2015 t2

题目:
BZOJ

解析:
1.对于第一种操作,树剖基本操作
2.对于第三种操作,简单的查询
3.对于第二种操作,设 w 为在某一子树上的增量,u为根结点,v为任意一节点;
则增量对于V的贡献为w (deep[v] - deep[u] + 1). 拆开来看,w deep[v],deep[v]在dfs中已预处理出来,剩下的量可以在根节点上维护。

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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

const int N = 1e5 + 15;

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

int n, m, size[N], son[N], li[N], tr[N], retr[N], deep[N], fa[N], w[N], tot;

struct Edge{
int next, to;
}E[N * 2]; int head[N], ecnt = 1;

inline void add(int a, int b)
{
E[++ecnt] = (Edge) {head[a], b}; head[a] = ecnt;
E[++ecnt] = (Edge) {head[b], a}; head[b] = ecnt;
}

#define FOR(x) for(int e = head[x]; e; e = E[e].next)

struct seg_t{
int l, r, lc, rc;
ll sum, id, su;
}a[N * 5];

inline void dfs1(int x, int f, int de)
{
deep[x] = de, fa[x] = f;
if(head[x] == 0) {
son[x] = x; return ;
}
FOR(x) {
int go = E[e].to;
if(go == fa[x]) continue;
dfs1(go, x, de + 1);
size[x] += size[go];
if(size[go] > size[son[x]] || !son[x]) {
son[x] = go;
}
}
return ;
}

inline void dfs2(int x, int f)
{
li[x] = f, tr[x] = ++tot, retr[tr[x]] = x;
if(son[x] == x) return ;
if(son[x]) dfs2(son[x], f);
FOR(x) {
int go = E[e].to;
if(go == fa[x]) continue;
if(go != son[x]) dfs2(go, go);
}
return ;
}

inline void build(int l, int r, int k)
{
a[k].l = l, a[k].r = r; a[k].sum = 0;
if(l == r) {
a[k].lc = a[k].rc = 0;
a[k].sum = (ll)w[retr[l]];
return ;
}
a[k].lc = (k << 1); a[k].rc = (k << 1) + 1;
int mid = (l + r) >> 1;
build(l, mid, k << 1); build(mid + 1, r, (k << 1) + 1);
a[k].sum = a[k << 1].sum + a[(k << 1) + 1].sum;
return ;
}

inline void change(int x, int k, ll v)
{
if(a[k].l == a[k].r && a[k].l == x)
{
a[k].sum += v;
return ;
}
int mid = (a[k].l + a[k].r) >> 1;
if(x <= mid) change(x, a[k].lc, v);
else change(x, a[k].rc, v);
a[k].sum = a[a[k].lc].sum + a[a[k].rc].sum;
return ;
}

inline void cson(int x, int k, ll v)
{
if(a[k].l == a[k].r && a[k].l == x)
{
a[k].id += v;
a[k].su += (ll)(deep[retr[x]] - 1) * v;
return ;
}
int mid = (a[k].l + a[k].r) >> 1;
if(x <= mid) cson(x, a[k].lc, v);
else cson(x, a[k].rc, v);
a[k].id = a[a[k].lc].id + a[a[k].rc].id;
a[k].su = a[a[k].lc].su + a[a[k].rc].su;
return ;
}

inline ll QQ(int l, int r, int k, int v)
{
if(a[k].l >= l && a[k].r <= r)
{
ll aa = a[k].sum + (ll)v * a[k].id - a[k].su;
return aa;
}
int mid = (a[k].l + a[k].r) >> 1;
ll an = 0;
if(l <= mid) an += QQ(l, r, a[k].lc, v);
if(r > mid) an += QQ(l, r, a[k].rc, v);
return an;
}

inline ll que(int u)
{
int uu = u, no = li[u];
ll a1 = 0; int du = deep[uu];
while(no != 1)
{
a1 += QQ(tr[no], tr[uu], 1, du);
uu = fa[no], no = li[uu];
}
a1 += QQ(1, tr[uu], 1, du);
return a1;
}

int main()
{

// freopen("4034.out", "w", stdout);
n = read(); m = read();
for(int i = 1; i <= n; ++i)
{
w[i] = read();
fa[i] = i; size[i] = 1;
}
for(int i = 1; i < n; ++i)
{
int u = read(), v = read();
add(u, v);
}
dfs1(1, 1, 1); dfs2(1, 1);
build(1, n, 1);
int x, y, z;
for(int i = 1; i <= m; ++i)
{
z = read(); x = read();
if(z == 1) {
y = read();
change(tr[x], 1, (ll)y);
}
if(z == 2) {
y = read();
cson(tr[x], 1, (ll)y);
}
if(z == 3) {
ll ans = que(x);
printf("%lldn", ans);
}
}
return 0;
}

EGOIST