877E - Danil and a Part-time Job
877E - Danil and a Part-time Job
给一颗树,结点有权值,更新子树所有结点,查询结点子树的和;
思路参考我上一篇文章
转换完之后就是区间更新和查询,然后更新sum就是把开关的房间调换一下;
更新add值就用对2取余,不能用异或~~(刚开始想着用异或1,后来发现,add的值会超过1)
代码(
注意main() 函数里 A[L[i]]=a; 调试了无数次才发现是这里的问题
)
因为把结点按照DFS序重新编号后,L[i]才是线段树维护序列的下标;
#include <iostream>
#include <cstdio>
#include <vector>
#include<cstring>
#define mem(x) memset(x,0,sizeof(x))
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
using namespace std;
const int N=200010;
vector<int> G[N];
int sum[N<<2],L[N],R[N],A[N],add[N<<2];
int fa[N];
int vv=0;
void init(int n)
{
for(int i=1;i<N;i++)
G[i].clear();
mem(sum);
mem(L);
mem(R);
mem(add);
mem(fa);
vv=0;
}
void dfs(int u)
{
vv++;
L[u]=vv;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v!=fa[u])dfs(v);
}
R[u]=vv;
}
void pu(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
void pd(int rt,int ln,int rn)
{
if(add[rt]){
add[rt<<1]=(add[rt]+add[rt<<1])%2;
add[rt<<1|1]=(add[rt]+add[rt<<1|1])%2;
//cout<<"add[3]="<<add[3]<<endl;
//cout<<"add[rt]="<<add[rt]<<endl;
//cout<<"add[rt|1]="<<add[rt<<1|1]<<endl;
//cout<<"pd-add-->";for(int i=1;i<=7;i++)cout<<add[i]<<' ';cout<<endl;
//if((rt<<1|1)==3){cout<<add[rt]<<' '<<add[rt<<1|1]<<' '<<(add[rt]+add[rt<<1|1])%2<<endl;}
sum[rt<<1]=ln-sum[rt<<1];
sum[rt<<1|1]=rn-sum[rt<<1|1];
add[rt]=0;
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=A[l];
return ;
}
int m=(l+r)>>1;
build(ls);build(rs);
pu(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
sum[rt]=(r-l+1)-sum[rt];
add[rt]=(add[rt]+1)%2;
return ;
}
int m=(l+r)>>1;
pd(rt,m-l+1,r-m);
if(L<=m)update(L,R,ls);
if(R>m)update(L,R,rs);
pu(rt);
}
int query(int L,int R,int l,int r,int rt)
{
//cout<<"add-->";for(int i=1;i<=20;i++)cout<<add[i]<<' ';cout<<endl;
//cout<<"sum-->";for(int i=1;i<=20;i++)cout<<sum[i]<<' ';cout<<endl;
if(L<=l&&r<=R)
{
return sum[rt];
}
int m=(l+r)>>1;
pd(rt,m-l+1,r-m);
int ans=0;
if(L<=m)ans+=query(L,R,ls);
if(R>m)ans+=query(L,R,rs);
pu(rt);
return ans;
}
int main()
{
int n,m;
while(~scanf("%d",&n))
{
int a;
init(n);
for(int i=2;i<=n;i++)
{
scanf("%d",&a);
fa[i]=a;
//G[i].push_back(a);
G[a].push_back(i);
}
dfs(1);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
A[L[i]]=a;
}
//cout<<"L[2]="<<L[2]<<' '<<"R[2]"<<R[2]<<endl;
build(1,n,1);
scanf("%d",&m);
char op[8];int x;
for(int i=1;i<=m;i++)
{
scanf("%s%d",op,&x);
if(op[0]=='g')cout<<query(L[x],R[x],1,n,1)<<endl;
else update(L[x],R[x],1,n,1);
}
}
return 0;
}