[树状数组 + 图论] CF383C Propagating tree 题解
做法是简单的。
我们知道题目其实就是按照树节点的深度分类修改,那么直接用两个树状数组分别维护奇数层和偶数层的情况。
由于他俩各司其职,你也不需要在修改的时候会多修多的问题,保证不修少就好了。修改使用 dfn 来实现把树映射到序列上。最后查询的时候看一下查询的节点的深度来决定输出哪个树状数组的值。
哦对了,这个树状数组就是实现区间修改和单点查询,板子P3368自己做。
#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
constexpr int N = 2e5 + 7;
using namespace std;
int x , y , opt , cnt , n , m , f , t , tot , a[N] , head[N] , depth[N] , dfn[N] , siz[N];
struct E {
int t , n;
}e[N << 1];
inline void add(int u , int v) {
e[++cnt].t = v , e[cnt].n = head[u] , head[u] = cnt;
}
void dfs(int s , int fa) {
depth[s] = depth[fa] + 1;
siz[s] = 1;
if(!dfn[s]) {
dfn[s] = ++tot;
}
for(register int i = head[s]; i ; i = e[i].n) {
int to = e[i].t;
if(to != fa) {
dfs(to , s);
siz[s] += siz[to];
}
}
}
struct Segment_Tree {
int t[N << 2];
inline void add(int x , int k) {
while(x <= n) {
t[x] += k;
x += lowbit(x);
}
}
inline int sum(int x) {
int res = 0;
while(x) {
res += t[x];
x -= lowbit(x);
}
return res;
}
inline void modify(int x , int y , int val) {
add(x , val) , add(y + 1 , -val);
}
}T1 , T2;
int main() {
ios :: sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
cin >> n >> m;
for(register int i = 1; i <= n; ++i) {
cin >> a[i];
}
for(register int i = 1; i < n; ++i) {
cin >> f >> t;
add(f , t) , add(t , f);
}
dfs(1 , 0);
while(m--) {
cin >> opt;
switch(opt) {
case 1 : {
cin >> x >> y;
if(depth[x] & 1) {
T1.modify(dfn[x] , dfn[x] + siz[x] - 1 , y);
T2.modify(dfn[x] , dfn[x] + siz[x] - 1 , -y);
}
else {
T1.modify(dfn[x] , dfn[x] + siz[x] - 1 , -y);
T2.modify(dfn[x] , dfn[x] + siz[x] - 1 , y);
}
break;
}
case 2 : {
cin >> x;
if(depth[x] & 1) {
cout << T1.sum(dfn[x]) + a[x] << '\n';
}
else {
cout << T2.sum(dfn[x]) + a[x] << '\n';
}
break;
}
}
}
return 0;
}