Description
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 i having 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:
- "1xval" — val is added to the value of node x;
- "2x" — 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.
Sample 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
3 3 0
Hint
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)
/**
题意:给一棵树,结点标记为 1到n,1号为根,
i号结点初始权值为a[i]。两种操作:
1 x val 将x结点权值加val,并且x的儿子结点加-val
孙子结点加 val .... 类推。
2 x 查询x结点的权值并输出。
分析:建树后DFS预处理每个结点的深度(可用01区分)
并按前序遍历标号并记录每颗子树的左右边界。
不妨规定0深度+val,1深度-val。
对于操作1,成段修改,根据x结点深度选择+-val;
对于操作2,单点查找,若该结点深度为1,取反。加初始值输出。
Author : WCB
Time : 2014/11/17
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N = 200010;
typedef long long LL;
int mak[N<<2];
int d[N];
int deep[N];
int le[N],ri[N];
vector<int>G[N];
int num;
void DFS(int x, int dep)
{
le[x] =++num;
deep[num] = dep;
for(int i=0; i<G[x].size(); i++)
{
int v = G[x][i];
if(le[v]!=-1)
{
continue;
}
DFS(v,dep^1);
}
ri[x] = num;
}
void update(int L, int R, int d, int l, int r, int rt)
{
if(L<=l && R>=r)
{
mak[rt]+=d;
return;
}
int m = l+r>>1;
if(L<=m) update(L,R,d,l,m,rt<<1);
if(R>m) update(L,R,d,m+1,r,rt<<1|1);
}
int query(int pos, int l, int r, int rt)
{
if(l==r) return deep[l]&1? -mak[rt] : mak[rt];
int m = l+r>>1;
if(mak[rt])
{
mak[rt<<1]+=mak[rt];
mak[rt<<1|1]+=mak[rt];
mak[rt] = 0;
}
return pos<=m ? query(pos,l,m,rt<<1) : query(pos,m+1,r,rt<<1|1);
}
int main()
{
//freopen("date.in","r",stdin);
int i,j,k,m,n,p,x,val;
while(scanf("%d%d",&n,&m)==2)
{
for(i=1; i<=n; i++) scanf("%d",d+i);
for(i=1; i<=n; i++) G[i].clear();
k = n-1;
while(k--)
{
scanf("%d%d",&i,&j);
G[i].push_back(j), G[j].push_back(i);
}
memset(le,-1,sizeof(le));
num = 0;
DFS(1,0);
memset(mak,0,sizeof(mak));
while(m--)
{
scanf("%d",&p);
if(p==1)
{
scanf("%d %d",&x,&val);
if(deep[le[x]]&1) val = -val;
update(le[x],ri[x],val,1,n,1);
}
else
scanf("%d",&k),
printf("%d\n",d[k]+query(le[k],1,n,1));
}
}
return 0;
}