这道题目给出了一颗树,并且有两种操作,一种是将以节点i为root的子树每个节点上的值取反,还有一种操作时查询以节点i为root的子树所有节点上的值得和。
节点上的值不是1就是0,初始皆为0;
直接在原有的树上操作是不行了的,因为题目需要频繁的修改子树,和查询子树,因此这道题目要用线段树。
我们要先用dfs将这个树遍历,之后形成一个线性序列。
比如
1
2 3 4
5 6 7 8 9
比如这棵树 dfs遍历之后的序列 是
1 2 5 6 3 4 7 8 9
我们可以看到每一颗子树的节点都在一个区间上。利用这个就可以写成成段更新的线段树了。
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
Author: CUI, Tianyi
Contest: ZOJ Monthly, March 2013
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
using namespace std;
#define MAXN 100010
#define lson l,m,root<<1
#define rson m+1,r,root<<1|1
struct nodes
{
int to,next;
}edge[100010];
int head[MAXN],p,e;
int l[MAXN],r[MAXN];
int node[MAXN<<2],col[MAXN<<2];
void dfs(int u)
{
l[u]=++p;
for(int i=head[u];i!=-1;i=edge[i].next)
dfs(edge[i].to);
r[u]=p;
}
void add(int a,int b) //parent: a child: b
{
edge[e].to=b;
edge[e].next=head[a];
head[a]=e++;
}
void push_up(int root)
{
node[root]=node[root<<1]+node[root<<1|1];
}
void push_down(int root,int m)
{
if(col[root])
{
col[root<<1]^=1;
col[root<<1|1]^=1;
node[root<<1]=(m-(m>>1))-node[root<<1];
node[root<<1|1]=(m>>1)-node[root<<1|1];
col[root]=0;
}
}
void build(int l,int r,int root)
{
col[root]=0;
if(l==r)
{
node[root]=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
push_up(root);
}
void update(int L,int R,int l,int r,int root)
{
if(l>=L && r<=R)
{
col[root]^=1;
node[root]=(r-l+1)-node[root];
return;
}
int m=(l+r)>>1;
push_down(root,r-l+1);
if(L<=m) update(L,R,lson);
if(R>m) update(L,R,rson);
push_up(root);
}
int query(int L,int R,int l,int r,int root)
{
if(l>=L && R>=r)
{
return node[root];
}
int ret=0,m=(l+r)>>1;
push_down(root,r-l+1);
if(L<=m) ret+=query(L,R,lson);
if(R>m) ret+=query(L,R,rson);
return ret;
}
int n,m,t;
char q[20];
int main()
{
while(~scanf("%d%d",&n,&m))
{
build(1,n,1);
memset(head,-1,sizeof(head)),e=0,p=0;
for(int i=2;i<=n;i++)
{
scanf("%d",&t);
add(t,i);
}
dfs(1);
for(int i=0;i<m;i++)
{
scanf("%s%d",q,&t);
if(q[0]=='q')
printf("%d\n",query(l[t],r[t],1,n,1));
else
update(l[t],r[t],1,n,1);
}
printf("\n");
}
return 0;
}