【CodeForces - 383C 】【 Propagating tree】

题目:

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;
}

猜你喜欢

转载自blog.csdn.net/qq_42505741/article/details/81605541