Propagating tree
题目连接
http://codeforces.com/contest/383/problem/C
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:
? "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.
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
Sample Output
3
3
0
HINT
题意
给出一颗有n个节点并一1为根节点的树,每个节点有它的权值,现在进行m次操作,操作分为添加和查询,当一个节点的权值添加val,则它的孩子节点的权值要添加-b。
题解:
dfs序+树状数组
学过或者没学过树链剖分的小朋友应该知道dfs序可以使得任意节点的子树变成一段连续的区间,这样就可以进行区间修改了。
但是这道题对子树层数的不同,操作也不一样,确实很麻烦呀。
我也是一脸懵逼,看完题解才发现原来如此神奇!!
其实我们可以把树分层,分成奇数层和偶数层(根据到根节点的距离),然后建两个树状数组,如果是对奇数层的点进行操作那么就给第一个树状数组相应的区间加上val,如果是偶数层就更新第二个树状数组。
这样对于某个节点i(假设是奇数层),那么此刻权值就是树状数组1-树状数组2。
感觉这种分层的思想很是神奇。
#include<bits/stdc++.h> using namespace std; #define ll long long #define N 400050 int n,m,cnt,w[N],a[N],c[2][N]; int dp[N],rk[N],kth[N],size[N]; int tot,last[N]; struct Edge{int from,to,s;}edges[N<<1]; template<typename T>void read(T&x) { ll k=0; char c=getchar(); x=0; while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar(); if (c==EOF)exit(0); while(isdigit(c))x=x*10+c-'0',c=getchar(); x=k?-x:x; } void read_char(char &c) {while(!isalpha(c=getchar())&&c!=EOF);} void AddEdge(int x,int y) { edges[++tot]=Edge{x,y,last[x]}; last[x]=tot; } void dfs(int x,int pre) { dp[x]=1-dp[pre]; rk[x]=++cnt; kth[cnt]=x; size[x]=1; for(int i=last[x];i;i=edges[i].s) { Edge &e=edges[i]; if (e.to==pre)continue; dfs(e.to,x); size[x]+=size[e.to]; } } void update(int *c,int x,int tt) {while(x<=n){c[x]+=tt;x+=x&-x;}} int get_sum(int *c,int x) {int ans=0;while(x){ans+=c[x];x-=x&-x;}return ans;} int main() { #ifndef ONLINE_JUDGE freopen("aa.in","r",stdin); #endif read(n);read(m); for(int i=1;i<=n;i++)read(w[i]); for(int i=1;i<=n-1;i++) { int x,y; read(x); read(y); AddEdge(x,y); AddEdge(y,x); } dfs(1,0); for(int i=1;i<=m;i++) { int id,x,val; read(id); if (id==1) { read(x); read(val); update(c[dp[x]],rk[x],val); update(c[dp[x]],rk[x]+size[x],-val); } if (id==2) { read(x); int ans=get_sum(c[dp[x]],rk[x])-get_sum(c[1-dp[x]],rk[x]); ans+=w[x]; printf("%d\n",ans); } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。