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
题目大意:有棵根节点为1的树,共有n个节点。有m次询问。第二行为从2--->n各个节点对应的父亲节点编号。下面的m行是询问,o ai表示将节点为ai的子树所有节点的值进行异或即0变1,1变0。q ai表示询问目前该子树的节点的和值为多少。
解题思路:其实这个题目重点在如何将多子树转化成线段树进行操作。我们如果重新将树编号,那么可以让每个节点对应一段区间。从根节点1开始深搜,编号为1,每当搜到一个节点,就让编号的值加1,让这个编号等于该节点的区间左端点,等把该节点的所有子节点访问完后,将这时的编号赋值给该节点的区间右端点。这时这个区间内的所有节点都是该节点的子节点。 后边就是区间更新的问题了。
#include<bits/stdc++.h> using namespace std; #define mid (L+R)/2 #define lson rt*2,L,mid #define rson rt*2+1,mid+1,R const int maxn=1e5+50; vector<int>G[maxn]; int Lt[maxn],Rt[maxn]; int sumv[maxn*4],lazy[maxn*4]; int n,cn; void dfs(int u){ Lt[u]=++cn; int v; for(int i=0;i<G[u].size();i++){ v=G[u][i]; dfs(v); } Rt[u]=cn; } void build(int rt,int L,int R){ sumv[rt]=lazy[rt]=0; if(L==R) return ; build(lson); build(rson); } void PushDown(int rt,int L,int R){ if(lazy[rt]){ lazy[rt*2]^=1; lazy[rt*2+1]^=1; sumv[rt*2]=(mid-L+1)-sumv[rt*2]; sumv[rt*2+1]=(R-mid)-sumv[rt*2+1]; lazy[rt]=0; } } void PushUp(int rt){ sumv[rt]=sumv[rt*2]+sumv[rt*2+1]; } void update(int rt,int L,int R,int l_ran,int r_ran){ if(l_ran<=L&&R<=r_ran){ lazy[rt]^=1; sumv[rt]=R-L+1-sumv[rt]; return ; } PushDown(rt,L,R); if(l_ran<=mid){ update(lson,l_ran,r_ran); } if(r_ran>mid){ update(rson,l_ran,r_ran); } PushUp(rt); } int query(int rt,int L,int R,int l_ran,int r_ran){ if(l_ran<=L&&R<=r_ran){ return sumv[rt]; } int ret=0; PushDown(rt,L,R); //lazy下放 if(l_ran<=mid){ ret+=query(lson,l_ran,r_ran); } if(r_ran>mid){ ret+=query(rson,l_ran,r_ran); } return ret; } int main(){ char s[4]; int m,subt,a,res; while(scanf("%d%d",&n,&m)!=EOF){ build(1,1,n); for(int i=0;i<=n;i++) G[i].clear(); for(int i=2;i<=n;i++){ scanf("%d",&a); G[a].push_back(i); } cn=0; dfs(1); for(int i=0;i<m;i++){ scanf("%s%d",s,&subt); if(s[0]=='o'){ update(1,1,n,Lt[subt],Rt[subt]); }else{ res=query(1,1,n,Lt[subt],Rt[subt]); printf("%d\n",res); } }printf("\n"); } return 0; } /* 6 5 1 2 1 4 4 o 4 q 4 q 5 q 6 q 1 */