题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686
题意:给定一颗有根树,每个节点有0和1两种值。有两种操作:o a操作,把以a为根节点的子树的权值全部取反;q a操作,求以a为根节点的子树权值为1的节点个数。
先求出树的先序遍历结果,并且记录每颗子树的节点个数,然后就可以用线段树维护了。。
1 //STATUS:C++_AC_240MS_6524KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,102400000") 25 //using namespace __gnu_cxx; 26 //define 27 #define pii pair<int,int> 28 #define mem(a,b) memset(a,b,sizeof(a)) 29 #define lson l,mid,rt<<1 30 #define rson mid+1,r,rt<<1|1 31 #define PI acos(-1.0) 32 //typedef 33 typedef long long LL; 34 typedef unsigned long long ULL; 35 //const 36 const int N=100010; 37 const int INF=0x3f3f3f3f; 38 const int MOD=1e+7,STA=8000010; 39 const LL LNF=1LL<<60; 40 const double EPS=1e-8; 41 const double OO=1e15; 42 const int dx[4]={-1,0,1,0}; 43 const int dy[4]={0,1,0,-1}; 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 45 //Daily Use ... 46 inline int sign(double x){return (x>EPS)-(x<-EPS);} 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 50 template<class T> inline T Min(T a,T b){return a<b?a:b;} 51 template<class T> inline T Max(T a,T b){return a>b?a:b;} 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 56 //End 57 58 int first[N],next[N*2],e[N*2],ra[N],id[N],sum[N],one[N<<2],rev[N<<2]; 59 int n,m,mt,cnt,ans; 60 61 void adde(int a,int b) 62 { 63 e[mt]=b; 64 next[mt]=first[a],first[a]=mt++; 65 e[mt]=a; 66 next[mt]=first[b],first[b]=mt++; 67 } 68 69 int dfs(int u,int fa) 70 { 71 ra[cnt++]=u; 72 int i,j; 73 sum[u]=1; 74 for(i=first[u];i!=-1;i=next[i]){ 75 if(e[i]==fa)continue; 76 sum[u]+=dfs(e[i],u); 77 } 78 return sum[u]; 79 } 80 81 void pushdown(int rt,int llen,int rlen) 82 { 83 if(rev[rt]){ 84 rev[rt]=0; 85 one[rt<<1]=llen-one[rt<<1]; 86 one[rt<<1|1]=rlen-one[rt<<1|1]; 87 rev[rt<<1]^=1,rev[rt<<1|1]^=1; 88 } 89 } 90 91 void update(int l,int r,int rt,int L,int R) 92 { 93 if(L<=l && r<=R){ 94 rev[rt]^=1; 95 one[rt]=r-l+1-one[rt]; 96 return ; 97 } 98 int mid=(l+r)>>1; 99 pushdown(rt,mid-l+1,r-mid); 100 if(L<=mid)update(lson,L,R); 101 if(R>mid)update(rson,L,R); 102 one[rt]=one[rt<<1]+one[rt<<1|1]; 103 } 104 105 void query(int l,int r,int rt,int L,int R) 106 { 107 if(L<=l && r<=R){ 108 ans+=one[rt]; 109 return ; 110 } 111 int mid=(l+r)>>1; 112 pushdown(rt,mid-l+1,r-mid); 113 if(L<=mid)query(lson,L,R); 114 if(R>mid)query(rson,L,R); 115 one[rt]=one[rt<<1]+one[rt<<1|1]; 116 } 117 118 int main() 119 { 120 // freopen("in.txt","r",stdin); 121 int i,j,t; 122 char op[2]; 123 while(~scanf("%d%d",&n,&m)) 124 { 125 mem(first,-1);mt=0; 126 for(i=2;i<=n;i++){ 127 scanf("%d",&t); 128 adde(t,i); 129 } 130 cnt=1; 131 dfs(1,-1); 132 for(i=1;i<=n;i++)id[ra[i]]=i; 133 134 mem(one,0);mem(rev,0); 135 while(m--){ 136 scanf("%s%d",op,&t); 137 if(op[0]=='o'){ 138 update(1,n,1,id[t],id[t]+sum[t]-1); 139 } 140 else { 141 ans=0; 142 query(1,n,1,id[t],id[t]+sum[t]-1); 143 printf("%d\n",ans); 144 } 145 } 146 putchar('\n'); 147 } 148 return 0; 149 }