ZOJ Monthly, March 2013 - A A Simple Tree Problem
http://acm.zju.edu.cn/onlinejudge/showContestProblem.do?problemId=4959
题意:给一棵树,树的每个节点初始值为0,要求支持两种操作:
o k : 将k下的子树值取反
q k : 查询k下的子树值有多少个为1
思路:化树结构为线性,每个点管理一个区间。
View Code
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; const int maxn = 200005; struct nd{ int v,next; }edge[maxn]; int hp[maxn]; int ls[maxn][2];//k管理的区间为[ls[k][0],ls[k][1]] int as[maxn*8][3]; int ecnt; int n,m; void add(int u,int v) { edge[ecnt].v = v; edge[ecnt].next = hp[u]; hp[u] = ecnt++; } int dfs(int x) { ls[x][0]= ls[x][1] = ecnt++; for(int i = hp[x]; i; i = edge[i].next){ int v = edge[i].v; ls[x][1] = dfs(v); } return ls[x][1]; } void doit(int rt){int tmp=as[rt][0];as[rt][0]=as[rt][1];as[rt][1]=tmp;} void pushUp(int rt) { as[rt][0] = as[rt<<1][0] + as[rt*2+1][0]; as[rt][1] = as[rt<<1][1] + as[rt*2+1][1]; } void pushDown(int rt) { as[rt][2] ^= 1; as[rt*2][2] ^= 1; as[rt*2+1][2] ^= 1; doit(rt<<1); doit(rt*2+1); } void build(int rt,int l,int r) { int mid = (l + r) >> 1; if(l==r){ as[rt][0] = 1; as[rt][1] = 0; as[rt][2] = 0; }else{ build(rt<<1,l,mid); build((rt<<1)+1,mid+1,r); pushUp(rt); } } void update(int rt,int l,int r,int L,int R) { int mid = (l + r) >> 1; if(L<=l && r<=R){ doit(rt); as[rt][2] ^= 1; return; } if(as[rt][2])pushDown(rt); if(L<=mid)update(rt<<1,l,mid,L,R); if(mid<R)update(rt*2+1,mid+1,r,L,R); pushUp(rt); } int ans; void query(int rt,int l,int r,int L,int R) { int mid = (l + r) >> 1; if(L<=l && r<=R){ ans += as[rt][1]; return; } if(as[rt][2])pushDown(rt); if(L<=mid)query(rt<<1,l,mid,L,R); if(mid<R)query(rt*2+1,mid+1,r,L,R); pushUp(rt); } int main() { int i,k; while(scanf("%d %d",&n,&m)==2){ for(i = 0; i <= n; ++ i)hp[i]=0; memset(as,0,sizeof(as)); ecnt = 1; for(i = 2; i <= n; ++ i){ scanf("%d",&k); add(k,i); } ecnt = 1; dfs(1); build(1,1,n); while(m--){ char op[2]; scanf("%s %d",op,&k); if(op[0]=='o')update(1,1,n,ls[k][0],ls[k][1]); else{ ans = 0; query(1,1,n,ls[k][0],ls[k][1]); printf("%d\n",ans); } } puts(""); } return 0; }