题目:
Iahub likes trees very much. Recently he discovered an interesting tree named propagating tree. The tree consists of n nodes numbered from 1 to n, each node ihaving an initial value ai. The root of the tree is node 1.
This tree has a special property: when a value val is added to a value of node i, the value -val is added to values of all the children of node i. Note that when you add value -val to a child of node i, you also add -(-val) to all children of the child of node i and so on. Look an example explanation to understand better how it works.
This tree supports two types of queries:
- "1 x val" — val is added to the value of node x;
- "2 x" — print the current value of node x.
In order to help Iahub understand the tree better, you must answer m queries of the preceding type.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 200000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 1000). Each of the next n–1 lines contains two integers vi and ui (1 ≤ vi, ui ≤ n), meaning that there is an edge between nodes vi and ui.
Each of the next m lines contains a query in the format described above. It is guaranteed that the following constraints hold for all queries: 1 ≤ x ≤ n, 1 ≤ val ≤ 1000.
Output
For each query of type two (print the value of node x) you must print the answer to the query on a separate line. The queries must be answered in the order given in the input.
Examples
Input
5 5 1 2 1 1 2 1 2 1 3 2 4 2 5 1 2 3 1 1 2 2 1 2 2 2 4
Output
3 3 0
Note
The values of the nodes are [1, 2, 1, 1, 2] at the beginning.
Then value 3 is added to node 2. It propagates and value -3 is added to it's sons, node 4 and node 5. Then it cannot propagate any more. So the values of the nodes are [1, 5, 1, - 2, - 1].
Then value 2 is added to node 1. It propagates and value -2 is added to it's sons, node 2 and node 3. From node 2 it propagates again, adding value 2 to it's sons, node 4 and node 5. Node 3 has no sons, so it cannot propagate from there. The values of the nodes are [3, 3, - 1, 0, 1].
You can see all the definitions about the tree at the following link: http://en.wikipedia.org/wiki/Tree_(graph_theory)
解题思路:树状数组+dfs
就是初始化时候给我们每个节点的值,之后有两种操作,1是修改当前节点的值(+val),且他的子节点都加相应的负值(-val),emmm,孙子节点(+val)依此进行下去,2是查询某个节点当前的值,并输出。
首先,要对树状数组进行分层,根奇偶来分层,然后开两个树状数组,因为当前节点的值,就是它爷爷的值-它父亲的值+原本它的值,就酱。
ac代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define maxn 200006
using namespace std;
typedef long long ll;
struct node{
int l;
int r;
int dep;//点所对应的类别
}a[maxn];
int n,m,idx,val,ans;
int va[maxn],bit[2][maxn];//开两个树状数组
vector<int > v[maxn];//建立二者的关系
bool vis[maxn];
int lowbit(int x)
{
return x&-x;
}
int sum(int i,int k)
{
int s=0;
while(i>0)
{
s+=bit[k][i];
i-= lowbit(i);
}
return s ;
}
void add(int i,int x,int k)
{
while(i<=n)
{
bit[k][i]+=x;
i+= lowbit(i);
}
} //不同于普通的树状数组的操作,这个增加了区分类别的操作。
void dfs(int k,int dep)//对树进行dfs
{
a[k].l=idx++;
vis[k]=1;
a[k].dep=dep;//对点分类
for(int i=0;i<(int)v[k].size();i++)
{//神奇的vector
if(!vis[v[k][i]])
dfs(v[k][i],dep^1);
}
a[k].r=idx-1;
}//明确当前节点的出入度
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&va[i]);
}
int u,k;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&k);
v[u].push_back(k);
v[k].push_back(u);//建立关系
}
idx=1;
dfs(1,1);
while(m--)
{
int g;
scanf("%d",&g);
if(g==1)
{
scanf("%d%d",&u,&val);
add(a[u].l,val,a[u].dep); //更新对应的树状数组
add(a[u].r+1,-val,a[u].dep);//本身加val 子树加-val
}
if(g==2)
{
scanf("%d",&u);
ans=sum(a[u].l,a[u].dep)-sum(a[u].l,a[u].dep^1); //计算两个树状数组分别对答案的贡献
printf("%d\n",ans+va[u]);//明确当前节点的值就是爷爷的增加值-父亲的增加值 +本身的值
}
}
return 0;
}