题目链接:http://codeforces.com/contest/877/problem/E;
题目大意:有一棵以1为根节点,n个节点的树,每个节点上都有一盏灯,一开始告诉你各个节点上的灯是否亮着。接下来有q次操作,操作分为如下两种:
1、pow v : 使得以v为根节点的子树中的节点开着的灯关掉,关着的灯开起来;
2、get v : 查询以v为根节点的子树中有多少个节点的灯是亮着的。
题目思路:根据dfs序的性质,子树中的节点的编号都是连续的,那么就可以将整个树上的节点的dfs序的编号放置线段树上,用线段树来维护区间内灯亮的个数,pow操作时只需要令 num[rt] = (r - l + 1) - num[rt] 即可,查询就是简单的线段树区间查询,具体实现看代码吧。
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MX = 2e5+7;
int n,tot;
int in[MX],out[MX];//存储dfs序。
int num[MX<<2],lazy[MX<<2];
vector<int>E[MX];
void add_edge(int u,int v){
E[u].push_back(v);
E[v].push_back(u);
}
void dfs(int u,int fa){
in[u] = ++tot;
for(int i = 0;i < E[u].size();i++){
int v = E[u][i];
if(v == fa) continue;
dfs(v,u);
}
out[u] = tot;
}
void push_up(int rt){
num[rt] = num[rt<<1] + num[rt<<1|1];
}
void push_down(int l,int r,int rt){
if(lazy[rt]){
lazy[rt<<1] ^= 1;
lazy[rt<<1|1] ^= 1;
//由于每次都是0变成1,1变成0的操作,所以懒惰标记用异或运算来更新;
int m = (l + r) >> 1;
num[rt<<1] = (m - l + 1) - num[rt<<1];
num[rt<<1|1] = (r - m) - num[rt<<1|1];
lazy[rt] = 0;
}
}
void build(int l,int r,int rt){
lazy[rt] = num[rt] = 0;
if(l == r) return;
int m = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void update(int L,int R,int l,int r,int rt){
if(L <= l && r <= R){
num[rt] = (r-l+1)-num[rt];
//原来这个区间中亮灯的数是num[rt],那么进行pow操作之后亮灯数就变为(r-l+1)-num[rt];
lazy[rt] ^= 1;
return;
}
int m = (l + r) >> 1;
push_down(l,r,rt);
if(L <= m) update(L,R,lson);
if(R > m) update(L,R,rson);
push_up(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L <= l && r <= R) return num[rt];
int m = (l + r) >> 1;
int ret = 0;
push_down(l,r,rt);
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
}
int main(){
scanf("%d",&n);
for(int i = 2;i <= n;i++){
int to;scanf("%d",&to);
add_edge(i,to);
}
dfs(1,-1);
build(1,n,1);
for(int i = 1;i <= n;i++){
int t;scanf("%d",&t);
if(t) update(in[i],in[i],1,n,1);
}
int q;scanf("%d",&q);
while(q--){
int to;
char op[10];
scanf("%s%d",op,&to);
int L = in[to],R = out[to];
if(op[0] == 'g') printf("%d\n",query(L,R,1,n,1));
else update(L,R,1,n,1);
}
return 0;
}