给出一个具有N个点的树,现在给出两种操作:
1.get x,表示询问以x作为根的子树中,1的个数。
2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0).
思路:
直接Dfs序加一个线段树维护一下区间更新就行了= =
Ac代码:
#include<stdio.h>
#include<string.h>
#include<bitset>
#include<vector>
#include<iostream>
using namespace std;
#define N 200005
int cnt;
vector<int>mp[350000];
int L[350000];
int R[350000];
void Dfs(int u,int from)
{
L[u]=++cnt;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from)continue;
Dfs(v,u);
}
R[u]=cnt;
}
/*********************************/
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[250000*4];
int flag[250000*4];
void pushup(int rt)
{
tree[rt]=(tree[rt*2]+tree[rt*2+1]);
}
void pushdown(int l,int r,int rt)
{
if(flag[rt])
{
int m=(l+r)/2;
flag[rt*2]^=1;
flag[rt*2+1]^=1;
tree[rt*2]=(m-l+1)-tree[rt*2];
tree[rt*2+1]=(r-(m+1)+1)-tree[rt*2+1];
flag[rt]=0;
}
}
void build(int l,int r,int rt)
{
flag[rt]=0;
if(l==r)
{
tree[rt]=0;return ;
}
int m=(l+r)/2;
pushdown(l,r,rt);
build(lson);build(rson);pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
tree[rt]=r-l+1-tree[rt];
flag[rt]^=1;
return ;
}
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)update(L,R,lson);
if(R>m)update(L,R,rson);
pushup(rt);
return ;
}
int query(int L,int R,int l,int r,int rt)
{
if(l>=L&&r<=R)
{
return tree[rt];
}
int ans=0;
pushdown(l,r,rt);
int m=(l+r)/2;
if(L<=m)ans+=query(L,R,lson);
if(R>m)ans+=query(L,R,rson);
pushup(rt);
return ans;
}
/*********************************/
int main()
{
int n;
while(~scanf("%d",&n))
{
cnt=0;
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=2;i<=n;i++)
{
int x;scanf("%d",&x);
mp[x].push_back(i);
mp[i].push_back(x);
}
Dfs(1,-1);
build(1,n,1);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
if(x==1)
{
update(L[i],L[i],1,n,1);
}
}
int q;
scanf("%d",&q);
while(q--)
{
char s[15];
scanf("%s",s);
int x;scanf("%d",&x);
int l=L[x],r=R[x];
if(s[0]=='g')
{
printf("%d\n",query(l,r,1,n,1));
}
else
{
update(l,r,1,n,1);
}
}
}
}