题目大意:
有一棵树,对这个树有两种操作:1:表示为(1 x val),在编号为x的节点上加上val,然后给x节点的每个儿子加上- val,再给每个儿子的儿子加上-(- val),一直加到没有儿子为止。2:表示为(2 x)查询x节点上的值。
思路:
首先通过dfs将树抽象成树状数组,然后以和根节点的层数关系作为d,开两个树状数组分别计算添加值和减少值。
#include<bits/stdc++.h>
using namespace std;
#define N 200005
int bit[2][N], cnt, n;
struct Node
{
int l, r, val, d;
}node[N];
vector<int> g[N];
void dfs(int u, int fa, int d)
{
node[u].l=++cnt;node[u].d=d;
for(int i=0; i<g[u].size(); i++)
{
int v=g[u][i];
if(v==fa) continue;
dfs(v, u, 1-d);
}
node[u].r=cnt;
}
void modify(int x, int val, int *sum)
{
while(x<=n)
{
sum[x]+=val;
x+=(x&(-x));
}
}
int getsum(int x, int *sum)
{
int ret=0;
while(x>0)
{
ret+=sum[x];
x-=(x&(-x));
}
return ret;
}
int main()
{
int m, u, v, op;
while(scanf("%d%d", &n, &m)!=EOF)
{
cnt=0;
memset(bit, 0, sizeof(bit));
for(int i=1; i<=n; i++)
{
scanf("%d", &node[i].val);
g[i].clear();
}
for(int i=1; i<n; i++)
{
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, -1, 0);
for(int i=1; i<=m; i++)
{
scanf("%d", &op);
if(op==1)
{
scanf("%d%d", &u, &v);
modify(node[u].l, v, bit[node[u].d]);
modify(node[u].r+1, -v, bit[node[u].d]);
modify(node[u].l, -v, bit[1-node[u].d]);
modify(node[u].r+1, v, bit[1-node[u].d]);
}
else
{
scanf("%d", &u);
printf("%d\n", node[u].val+getsum(node[u].l, bit[node[u].d]));
}
}
}
return 0;
}