题目链接:Click here~~
题意:
给一颗确定的树,每个节点只有 0 和 1 两种状态。
两种操作:1、将某颗子树的0变1,1变0。
2、询问某颗子树的1的个数。
解题思路:
一看这两种操作,很容易就联想到了线段树,但问题是,区间在哪里???
由于操作都是对一颗树进行的,我们要想办法把它和区间联系起来。
不妨把 每个节点都看做一个数,每棵树都看做一个区间。
因为一共有 n 个点,我们把树根看做1,区间看做 [1,n]。
树根的孩子看做多少呢?2、3、4、5、6?
显然是不可以的,因为这样对 “2” 这颗树操作的时候,"2" 的子树不再是一段区间。
所以,3 应该让 "2" 的孩子来当。
…… 依次类推,怎么样,很像递归吧?
如果没懂的话,画个图仔细想想吧。
做法嘛,dfs 一下就好了。
转化成区间之后,就是很简单的 线段树 问题了。
#include <vector>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define lson u<<1
#define rson u<<1|1
const int N = 1e5+3;
vector<int> g[N];
struct Int
{
int a,b;
}I[N];
int id;
void dfs(int u)
{
I[u].a = ++id;
for(int i=0;i<(int)g[u].size();i++)
dfs(g[u][i]);
I[u].b = id;
}
struct SegTree
{
int l,r,sum,lazy;
inline int mid()
{
return l+r >> 1;
}
inline int len()
{
return r-l;
}
}T[N<<2];
void push_down(int u)
{
if(!T[u].lazy)
return ;
T[lson].sum = T[lson].len() - T[lson].sum;
T[rson].sum = T[rson].len() - T[rson].sum;
T[lson].lazy ^= 1;
T[rson].lazy ^= 1;
T[u].lazy = 0;
}
void push_up(int u)
{
T[u].sum = T[lson].sum + T[rson].sum;
}
void build(int u,int l,int r)
{
T[u].l = l , T[u].r = r;
T[u].sum = T[u].lazy = 0;
if(l == r-1)
{
return ;
}
int m = T[u].mid();
build(lson,l,m);
build(rson,m,r);
}
void updata(int u,int l,int r)
{
if(l == T[u].l && r == T[u].r)
{
T[u].sum = T[u].len() - T[u].sum;
T[u].lazy ^= 1;
return ;
}
push_down(u);
int m = T[u].mid();
if(r <= m)
updata(lson,l,r);
else if(l >= m)
updata(rson,l,r);
else
{
updata(lson,l,m);
updata(rson,m,r);
}
push_up(u);
}
int query(int u,int l,int r)
{
if(l == T[u].l && r == T[u].r)
return T[u].sum;
push_down(u);
int m = T[u].mid();
if(r <= m)
return query(lson,l,r);
else if(l >= m)
return query(rson,l,r);
else
return query(lson,l,m) + query(rson,m,r);
}
int main()
{
int n,Q,u;
char cmd[5];
while(~scanf("%d%d",&n,&Q))
{
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=2;i<=n;i++)
{
int num;
scanf("%d",&num);
g[num].push_back(i);
}
id = 0;
dfs(1);
build(1,1,n+1);
while(Q--)
{
scanf("%s%d",cmd,&u);
if(cmd[0] == 'o')
updata(1,I[u].a,I[u].b+1);
else
printf("%d\n",query(1,I[u].a,I[u].b+1));
}
puts("");
}
return 0;
}