题目链接:codeforces 877-E


题目大意:一棵树上,有些灯亮着,有些灯暗的,我们每次可以查询某个节点的亮灯个数,或者改变某个子树的暗亮情况(暗变成亮,亮变成暗)。


比较简单的dfs序,然后用线段树区间亮的个数即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,q,cnt,st[N],ed[N],a[N];
int head[N],nex[N],to[N],tot;
struct node{
	int l,r,sum,lazy;
}t[N<<2];
inline void add(int a,int b){
	to[++tot]=b; nex[tot]=head[a]; head[a]=tot;
}
void dfs(int x){
	st[x]=++cnt;
	for(int i=head[x];i;i=nex[i])	dfs(to[i]);
	ed[x]=cnt;
}
inline void push_up(int p){
	t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
}
inline void push_down(int p){
	if(t[p].lazy){
		t[p<<1].lazy^=1;	t[p<<1|1].lazy^=1;
		t[p<<1].sum=(t[p<<1].r-t[p<<1].l+1-t[p<<1].sum);
		t[p<<1|1].sum=(t[p<<1|1].r-t[p<<1|1].l+1-t[p<<1|1].sum);
		t[p].lazy=0;
	}
}
void build(int p,int l,int r){
	t[p].l=l;	t[p].r=r;
	if(l==r)	return ;	int mid=l+r>>1;
	build(p<<1,l,mid);	build(p<<1|1,mid+1,r);
}
void updata(int p,int x){
	if(t[p].l==t[p].r){
		t[p].sum=1;	return ;
	}
	int mid=t[p].l+t[p].r>>1;
	if(x<=mid)	updata(p<<1,x);
	else	updata(p<<1|1,x);
	push_up(p);
}
void change(int p,int l,int r){
	if(t[p].l==l&&t[p].r==r){
		t[p].lazy^=1;	t[p].sum=(r-l+1-t[p].sum);	return ;
	}
	push_down(p);	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	change(p<<1,l,r);
	else if(l>mid)	change(p<<1|1,l,r);
	else	change(p<<1,l,mid),change(p<<1|1,mid+1,r);
	push_up(p);
}
int ask(int p,int l,int r){
	if(t[p].l==l&&t[p].r==r)	return t[p].sum;
	push_down(p);	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	return ask(p<<1,l,r);
	else if(l>mid)	return ask(p<<1|1,l,r);
	else	return ask(p<<1,l,mid)+ask(p<<1|1,mid+1,r);
}
signed main(){
	scanf("%d",&n);
	for(int i=2;i<=n;i++){
		int x;	scanf("%d",&x);	add(x,i);
	}
	dfs(1);	build(1,1,n);
	for(int i=1;i<=n;i++){
		int x;	scanf("%d",&x);	if(x)	updata(1,st[i]);
	}
	scanf("%d",&q);	char op[5];	int x; 
	while(q--){
		scanf("%s %d",op,&x);
		if(op[0]=='g')	printf("%d\n",ask(1,st[x],ed[x]));
		else	change(1,st[x],ed[x]);
	}
	return 0;
}