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