codeforces#225-C - Propagating tree-dfs序(奇偶)+线段树

来源:互联网 发布:win7电脑连接网络 编辑:程序博客网 时间:2024/06/13 23:39

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);//同updateint 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;}


0 0
原创粉丝点击