Description
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
题意:题目有两种操作:o n 是将n的子树上的值全部取反。
q n是求n的子树上的和。
思路:一开始怎么想都没有办法和线段树结合在一起,还曾经傻逼的以为他就是二叉树0.0 经过师兄的点拨
线段树是对区间的修改,所以可以将这这棵多叉树中各节点的子树转化成一个一个连续的区间,具体操作是使用DFS遍历。
特别要注意的是:要将数组清空,setv 和 v 容器
CODE:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
const int inf=0xfffffff;
typedef long long ll;
using namespace std;
const int Max=100005;
vector<int>v[Max];
struct node
{
int a,b;
}point[Max];
int N,M,sum[Max<<2],setv[Max<<2];
int id;
void dfs(int ii)
{
point[ii].a=++id;
for(int i=0;i<v[ii].size();i++)
dfs(v[ii][i]);
point[ii].b=id;
}
void build(int pos,int l,int r)
{
if(l==r){
sum[pos]=0;
}
else{
int mid=(l+r)/2;
build(pos*2,l,mid);
build(pos*2+1,mid+1,r);
sum[pos]=sum[pos*2]+sum[pos*2+1];
}
}
void maintain(int pos)
{
sum[pos]=sum[pos*2]+sum[pos*2+1];
}
void pushdown(int pos,int l,int r)
{
if(setv[pos])
{
int mid=(l+r)/2;
setv[pos*2]^=1;
setv[pos*2+1]^=1;
sum[pos*2]=(mid-l+1)-sum[pos*2];
sum[pos*2+1]=(r-mid)-sum[pos*2+1];
setv[pos]=0;
}
}
void update_section(int pos,int l,int r,int x,int y)
{
if(x<=l&&y>=r){
setv[pos]^=1;
sum[pos]=(r-l+1)-sum[pos];
}
else{
pushdown(pos,l,r);
int mid=(l+r)/2;
if(x<=mid) update_section(pos*2,l,mid,x,y);
if(y>mid) update_section(pos*2+1,mid+1,r,x,y);
maintain(pos);
}
}
int query_section(int pos,int l,int r,int x,int y)
{
int ans=0;
if(x<=l&&y>=r) return sum[pos];
else{
pushdown(pos,l,r);
int mid=(l+r)/2;
if(x<=mid) ans+=query_section(pos*2,l,mid,x,y);
if(y>mid) ans+=query_section(pos*2+1,mid+1,r,x,y);
return ans;
}
}
int main()
{
//freopen("in.in","r",stdin);
while(~scanf("%d%d",&N,&M)){
for(int i=1;i<=N;i++)
v[i].clear();
memset(setv,0,sizeof(setv));
build(1,1,N);
int n;
for(int i=2;i<=N;i++){
scanf("%d",&n);
v[n].push_back(i);
}
id=0;
dfs(1);
char c[4];
while(M--){
scanf("%s%d",c,&n);
if(c[0]=='o'){
update_section(1,1,N,point[n].a,point[n].b);
}
if(c[0]=='q'){
printf("%d\n",
query_section(1,1,N,point[n].a,point[n].b));
}
}
printf("\n");
}
return 0;
}