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
先用dfs对树进行先序遍历并记录下每个节点的位置pos[rt]和它的儿子数tot[rt],这样就将同一棵子树按先序顺序保存在连续的数组区间,然后就转化为线段树求解区间和问题,遍历+区间更新O(n+mlogn)复杂度
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 100005
vector<int> g[maxn]; //保存每个节点的儿子
int tot[maxn]; //每个节点的儿子数
int pos[maxn]; //每个节点转为数组后对应的位置
int n, m;
int count(int rt, int &cur) //先序遍历确定位置,并统计儿子数
{
pos[rt] = cur++;
int sum = 1;
for(int i = 0; i < g[rt].size(); i++)
sum += count(g[rt][i], cur);
tot[rt] = sum-1;
return sum;
}
int begin[4*maxn], end[4*maxn], sum[4*maxn];
bool lazy[4*maxn];
void build(int rt, int l, int r)
{
begin[rt] = l; end[rt] = r;
sum[rt] = 0; lazy[rt] = 0;
if(l == r)
return;
int m = (l+r)>>1;
build(2*rt, l, m);
build(2*rt+1,m+1,r);
}
int query(int rt, int ll, int rr)
{
int lc = 2*rt, rc =2*rt+1;
if(ll == begin[rt] && rr == end[rt])
return sum[rt];
else{
if(lazy[rt]){
sum[lc] = end[lc]-begin[lc]+1-sum[lc];
sum[rc] = end[rc]-begin[rc]+1-sum[rc];
lazy[lc] = !lazy[lc];
lazy[rc] = !lazy[rc];
lazy[rt] = 0;
}
}
int m = (begin[rt]+end[rt])>>1;
if(rr <= m)
return query(lc, ll, rr);
else if(ll > m)
return query(rc, ll, rr);
else
return query(lc,ll,m)+query(rc,m+1,rr);
}
void modify(int rt, int ll, int rr)
{
int lc = 2*rt, rc = 2*rt+1;
if(ll == begin[rt] && rr == end[rt]){
sum[rt] = end[rt]-begin[rt]+1-sum[rt];
lazy[rt] = !lazy[rt];
return;
}
else{
if(lazy[rt]){
sum[lc] = end[lc]-begin[lc]+1-sum[lc];
sum[rc] = end[rc]-begin[rc]+1-sum[rc];
lazy[lc] = !lazy[lc];
lazy[rc] = !lazy[rc];
lazy[rt] = 0;
}
}
int m = (end[rt]+begin[rt])>>1;
if(rr <= m)
modify(lc, ll, rr);
else if(ll > m)
modify(rc, ll, rr);
else{
modify(lc, ll, m);
modify(rc, m+1, rr);
}
sum[rt] = sum[lc]+sum[rc];
}
int main()
{
while(~scanf("%d %d", &n, &m)){
for(int i = 0; i <n+2; i++) g[i].clear();
int t;
for(int i = 0; i < n-1; i++){
scanf("%d", &t);
g[t].push_back(i+2);
}
int cur = 1;
count(1,cur);
build(1,1,n);
char op[2];
int num;
for(int i = 0 ; i < m; i++){
scanf("%s %d", op, &num);
if(op[0] == 'o')
modify(1, pos[num], pos[num]+tot[num]);
else
printf("%d\n", query(1, pos[num], pos[num]+tot[num]));
}
printf("\n");
}
return 0;
}