POJ3321
题目大意:1e5个点的树,节点值为1。1e5次操作,将节点的值异或1,或者求点x为根的子树的节点权值和。(树的根为1号点)
简单的DFS序问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=1e5+10; 6 int n,m; 7 struct edge 8 { 9 int u,v,nxt; 10 }e[maxn<<1]; 11 int head[maxn],js; 12 void addage(int u,int v) 13 { 14 e[++js].u=u;e[js].v=v; 15 e[js].nxt=head[u];head[u]=js; 16 } 17 int lt[maxn],rt[maxn],cnt,sz[maxn]; 18 bool ap[maxn]; 19 void dfs(int u,int fa) 20 { 21 lt[u]=++cnt; 22 for(int i=head[u];i;i=e[i].nxt) 23 { 24 int v=e[i].v; 25 if(v==fa)continue; 26 dfs(v,u); 27 } 28 rt[u]=cnt; 29 } 30 void change(int x,int y) 31 { 32 for(int i=x;i<=n;i+=i&(-i))sz[i]+=y; 33 } 34 int query(int x) 35 { 36 int ans=0; 37 for(int i=x;i>0;i-=i&(-i))ans+=sz[i]; 38 return ans; 39 } 40 int main() 41 { 42 scanf("%d",&n); 43 for(int u,v,i=1;i<n;++i) 44 { 45 scanf("%d%d",&u,&v); 46 addage(u,v);addage(v,u); 47 } 48 dfs(1,0); 49 scanf("%d",&m); 50 char s[3]; 51 int x; 52 while(m--) 53 { 54 scanf("%s%d",s,&x); 55 if(s[0]=='Q')printf("%d\n",rt[x]-lt[x]+1-query(rt[x])+query(lt[x]-1)); 56 else 57 { 58 if(ap[x]==0) 59 { 60 ap[x]=1; 61 change(lt[x],1); 62 } 63 else 64 { 65 ap[x]=0; 66 change(lt[x],-1); 67 } 68 } 69 } 70 return 0; 71 }