CodeForces 383C Propagating tree

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

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

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值