http://codeforces.com/problemset/problem/383/C
题意:给一棵树,根为1,根高度为1,
每次操作 两种
1:x,val, 把x节点加val,把其所有儿子-val,把儿子的儿子都+val,反复如此
2:查询某个节点的值
对每次操作,显然就是把该节点的所有子节点中,奇偶性与X相同的+val,不同的则-val,如此反复
我们先跑一遍dfs序,得到dfs序和每个节点深度,然后用dfs序建两颗线段树,一个是只保留深度为奇的节点,一颗只保留深度为偶的节点(其实直接建两个正常的树,只需要在查询的时候,奇数树上返回偶数深度节点值*0,奇数深度节点值*1即可,偶树同理)
那么每次操作,只需要 对 两个线段树 上下标为in【x】到out【X】的节点 分别 +val和 -val即可
最后每次查询。只需要在两棵树分别查询该节点值,最后返回他们的和
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
const int N=200005;
int tm[200005],dp[N];
int who[200005+50];
struct tree
{
int add[4*N] ,vaild[4*N];
void build(int l,int r,int i,int kind) // 线段树的建立;
{
add[i]=0;
if(l==r)
{
if (dp[who[l]]%2==kind)
{add[i]=tm[who[l]]; vaild[i]=1; }
return;
}
int mid=(l+r)>>1;
build(l,mid,i<<1,kind);
build(mid+1,r,i<<1|1,kind);
}
void pushDown(int i, int l, int r) //把i节点的延迟标记传递到左右儿子节点
{
if(add[i] != 0)
{
int mid = (l + r) >> 1;
add[i << 1] += add[i];
add[i << 1 | 1] += add[i];
add[i] = 0;
}
}
void update(int i, int l, int r, int ql, int qr, int val)
{
if(l > qr || ql > r)
return ;
if(l >= ql && r <= qr)
{
add[i] += val;
return ;
}
pushDown(i, l, r);
int mid = (l + r) >> 1;
update(i << 1, l, mid, ql, qr, val);
update(i << 1 | 1, mid + 1, r, ql, qr, val);
}
int query(int i, int l, int r, int ql, int qr)
{
if(l > qr || ql > r)
return 0;
if(l == r && r == qr)
return add[i]*vaild[i];
pushDown(i, l, r); //同update
int mid =( l + r) >> 1;
if (ql<=mid) return query(i << 1, l, mid, ql, qr) ;
else return query(i << 1 | 1, mid + 1, r, ql, qr);
}
};
int in[200005+50],out[200005+50],vis[200005+50];
vector<int > mp[200005];
int id=0;
void dfs1(int x,int cur)
{
in[x]=++id;
vis[x]=1;
dp[x]=cur;
who[id]=x; //记下本id指向的节点
int i;
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
if (!vis[v])
dfs1(v,cur+1);
}
out[x]=id;
}
tree odd,even;
int main()
{
int n ,i,x,y,m;
cin>>n>>m;
for (i=1;i<=n;i++)
scanf("%d",&tm[i]);
for (i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
dfs1(1,1);
odd.build(1,n,1,1);
even.build(1,n,1,0);
int op,val;
for (i=1;i<=m;i++)
{
scanf("%d",&op);
if (op==1)
{
scanf("%d%d",&x,&val);
if (dp[x]%2)
{
odd.update(1,1,n,in[x],out[x],val);
even.update(1,1,n,in[x],out[x],-val);
}
else
{
even.update(1,1,n,in[x],out[x],val);
odd.update(1,1,n,in[x],out[x],-val);
}
}
else
{
scanf("%d",&x);
printf("%d\n",odd.query(1,1,n,in[x],in[x])+even.query(1,1,n,in[x],in[x]));
}
/*for (int j=1;j<=n;j++)
printf("%d ",odd.query(1,1,n,in[j],in[j])+even.query(1,1,n,in[j],in[j]));
printf("*******\n");*/
}
return 0;
}