CF877E
Description
给定一棵权值只能为 \(1\) 或 \(0\) 的树,对其进行两种操作。
一种是将其中的某棵子树取反,另一种是询问某棵子树中 \(1\) 的个数。
Solution
比较板的线段树。
显然的,假设一棵大小为 \(x\) 的子树中有 \(y\) 个 1,那么这棵子树取反后就有 \(x-y\) 个 \(1\)。
题目只需要我们维护一种信息,然后这种信息的变换只有这一种方法,所以我们知道了这个性质就可以直接搞了。
根据区间修改维护懒标记的原理,当一个点的子树取反后,它的左右儿子都要取反,因此懒标记下传时也不断取反就可以了。
然后就做完了。
Code
#include<bits/stdc++.h>
#define maxn 2001000
#define INF 0x3f3f3f3f
//#define int long long
using namespace std;
int n,m,tot,cnt;
int a[maxn],head[maxn],lazy[maxn];
int sum[maxn],val[maxn],fa[maxn];
int dfn[maxn],top[maxn],son[maxn];
int dep[maxn],siz[maxn],pre[maxn];
struct edge{int fr,to,nxt;}e[maxn];
int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
return s*w;
}
void add(int fr,int to){
e[++tot].fr=fr;e[tot].to=to;
e[tot].nxt=head[fr];head[fr]=tot;
}
namespace Seg{
#define ls x<<1
#define rs x<<1|1
void pushup(int x){
sum[x]=sum[ls]+sum[rs];
}
void pushdown(int x,int ln,int rn){
if(!lazy[x]) return;
lazy[ls]^=1;
lazy[rs]^=1;
sum[ls]=ln-sum[ls];
sum[rs]=rn-sum[rs];
lazy[x]=0;
}
void build(int x,int l,int r){
if(l==r){sum[x]=a[pre[l]];return;}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R){
if(L<=l&&R>=r){sum[x]=r-l+1-sum[x],lazy[x]^=1;return;}
int mid=l+r>>1;pushdown(x,mid-l+1,r-mid);
if(L<=mid) update(ls,l,mid,L,R);
if(R>=mid+1) update(rs,mid+1,r,L,R);
pushup(x);
}
int query(int x,int l,int r,int L,int R){
if(L<=l&&R>=r)return sum[x];
int mid=l+r>>1,ans=0;pushdown(x,mid-l+1,r-mid);
if(L<=mid) ans+=query(ls,l,mid,L,R);
if(R>=mid+1) ans+=query(rs,mid+1,r,L,R);
return ans;
}
}
namespace Cut{
void dfs1(int x,int fat){
dep[x]=dep[fat]+1;
fa[x]=fat;siz[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int to=e[i].to;
if(to==fat) continue;
dfs1(to,x);siz[x]+=siz[to];
if(siz[to]>siz[son[x]])son[x]=to;
}
}
void dfs2(int x,int tp){
top[x]=tp;dfn[x]=++cnt;pre[cnt]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i;i=e[i].nxt){
int to=e[i].to;
if(to==fa[x]||to==son[x]) continue;
dfs2(to,to);
}
}
}
int main(){
n=read();
for(int i=2,fa;i<=n;i++) fa=read(),add(fa,i);
for(int i=1;i<=n;i++) a[i]=read();m=read();
Cut::dfs1(1,0);Cut::dfs2(1,1);Seg::build(1,1,n);
for(int i=1,pos;i<=m;i++){
string opt;cin>>opt;pos=read();
if(opt[0]=='g') printf("%d\n",Seg::query(1,1,n,dfn[pos],dfn[pos]+siz[pos]-1));
else if(opt[0]=='p') Seg::update(1,1,n,dfn[pos],dfn[pos]+siz[pos]-1);
}
return 0;
}