对线段树的区间更新有了初步的了解。。。
Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.
We define this kind of operation: given a subtree, negate all its labels.
And we want to query the numbers of 1's of a subtree.
Input
Multiple test cases.
First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)
Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.
Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.
Output
For each query, output an integer in a line.
Output a blank line after each test case.
Sample Input
3 2 1 1 o 2 q 1
Sample Output
1
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <math.h> #include <map> #include <queue> #include <sstream> #include <iostream> using namespace std; #define INF 0x3fffffff #define N 100100 int n,m; struct node { int to,next; }edge[2*N]; struct node1 { int b,d,mid; int flag,sum; }tnode[3*N]; int cnt,pre[N]; int savex[N],savey[N]; int id; // 线段树的区间更新初步了解! void add_edge(int u,int v) { edge[cnt].to=v; edge[cnt].next=pre[u]; pre[u]=cnt++; } void dfs(int s,int path) { int tmp; ++id; tmp=id; for(int p=pre[s];p!=-1;p=edge[p].next) { int v=edge[p].to; if(v!=path) { dfs(v,s); } } savex[s]=tmp; savey[s]=id; } void built(int b,int d,int s) { tnode[s].b=b; tnode[s].d=d; tnode[s].mid=(b+d)/2; tnode[s].sum=0; tnode[s].flag=0; if(b==d) return ; built(b,tnode[s].mid,2*s); built(tnode[s].mid+1,d,2*s+1); } void insert(int b,int d,int s) { if(tnode[s].b==b&&tnode[s].d==d) { tnode[s].flag^=1; tnode[s].sum=(d-b+1) - tnode[s].sum; return ; } if(tnode[s].flag!=0) { tnode[s].flag=0; tnode[2*s].flag^=1; tnode[2*s].sum=(tnode[2*s].d-tnode[2*s].b+1)-tnode[2*s].sum; tnode[2*s+1].flag^=1; tnode[2*s+1].sum=(tnode[2*s+1].d-tnode[2*s+1].b+1)-tnode[2*s+1].sum; } if(tnode[s].mid>=d) insert(b,d,2*s); else if(tnode[s].mid+1<=b) insert(b,d,2*s+1); else { insert(b,tnode[s].mid,2*s); insert(tnode[s].mid+1,d,2*s+1); } tnode[s].sum=tnode[2*s].sum+tnode[2*s+1].sum;//用up,和down就更好理解 } //这样就不需要放回了,更简单了... int find(int b,int d,int s) { if(tnode[s].b==b&&tnode[s].d==d) { return tnode[s].sum; } if(tnode[s].flag!=0) { tnode[s].flag=0; tnode[2*s].flag^=1; tnode[2*s].sum=(tnode[2*s].d-tnode[2*s].b+1)-tnode[2*s].sum; tnode[2*s+1].flag^=1; tnode[2*s+1].sum=(tnode[2*s+1].d-tnode[2*s+1].b+1)-tnode[2*s+1].sum; } if(tnode[s].mid>=d) return find(b,d,s*2); else if(tnode[s].mid+1<=b) return find(b,d,2*s+1); else return find(b,tnode[s].mid,s*2)+find(tnode[s].mid+1,d,2*s+1); } int main() { //freopen("//home//chen//Desktop//ACM//in.text","r",stdin); //freopen("//home//chen//Desktop//ACM//out.text","w",stdout); while(scanf("%d%d",&n,&m)!=EOF) { cnt=0; id=0; memset(pre,-1,sizeof(pre)); for(int i=2;i<=n;i++) { int tmp; scanf("%d",&tmp); add_edge(i,tmp); add_edge(tmp,i); } dfs(1,1); /////////////// built(1,n,1); for(int i=0;i<m;i++) { char sel; int tmp; cin>>sel; scanf("%d",&tmp); if(sel=='o') { insert(savex[tmp],savey[tmp],1); } else { printf("%d ",find(savex[tmp],savey[tmp],1)); } } printf(" "); } return 0; }