题目传送门
读题后发现,install操作实质是将根节点到节点这条链上所有点都赋值为1,uninstall操作是将以x节点为根的子树及其本身赋值为0,install求ans时便是先求出根节点到x节点间点权值和,再用x的深度减去它就行了,uninstall操作求ans便是求出子树的权值和及其本身,然后这些都可以通过树链剖分来完成。注意这里线段树是区间覆盖,不是区间加,有点小细节不同。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int n,m,x,index_,ans,cnt,first[N],Next[N],to[N];
int val[N],f[N],mson[N],id[N],dep[N],Top[N],siz[N],lazy[N];
string saber;
int Read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
return f*x;
}
void add(int a,int b)
{
index_++;
Next[index_]=first[a];
first[a]=index_;
to[index_]=b;
}
void dfs1(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u]=fa;
int maxn=-1;
for(int i=first[u];i;i=Next[i])
{
int v=to[i];
if(v==fa) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>maxn) maxn=siz[v],mson[u]=v;
}
}
void dfs2(int u,int zz)
{
Top[u]=zz;
cnt++;
id[u]=cnt;
if(mson[u]) dfs2(mson[u],zz);
for(int i=first[u];i;i=Next[i])
{
int v=to[i];
if(v==f[u]||v==mson[u]) continue;
dfs2(v,v);
}
}
void pushdown(int rt,int l,int r)
{
if(lazy[rt]==-1) return;
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
int mid=(l+r)>>1;
val[rt<<1]=(mid-l+1)*lazy[rt];
val[rt<<1|1]=(r-mid)*lazy[rt];
lazy[rt]=-1;
}
void update(int rt,int l,int r,int op,int ed,int k)
{
if(op<=l&&ed>=r)
{
lazy[rt]=k;
if(k==0)
val[rt]=0;
else
val[rt]=r-l+1;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(op<=mid) update(rt<<1,l,mid,op,ed,k);
if(ed>=mid+1) update(rt<<1|1,mid+1,r,op,ed,k);
val[rt]=val[rt<<1]+val[rt<<1|1];
}
int query(int rt,int l,int r,int op,int ed)
{
int sum=0;
if(op<=l&&ed>=r) return val[rt];
pushdown(rt,l,r);
int mid=(l+r)>>1;
if(op<=mid) sum+=query(rt<<1,l,mid,op,ed);
if(ed>=mid+1) sum+=query(rt<<1|1,mid+1,r,op,ed);
return sum;
}
void updateR(int u,int v,int k)
{
while(Top[u]!=Top[v])
{
if(dep[Top[u]]<dep[Top[v]]) swap(u,v);
update(1,1,n,id[Top[u]],id[u],k);
u=f[Top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
update(1,1,n,id[u],id[v],k);
}
int queryR(int u,int v)
{
int sum=0;
while(Top[u]!=Top[v])
{
if(dep[Top[u]]<dep[Top[v]]) swap(u,v);
sum+=query(1,1,n,id[Top[u]],id[u]);
u=f[Top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
sum+=query(1,1,n,id[u],id[v]);
return sum;
}
void updateT(int rt,int k)
{
update(1,1,n,id[rt],id[rt]+siz[rt]-1,k);
}
int queryT(int rt)
{
return query(1,1,n,id[rt],id[rt]+siz[rt]-1);
}
int main()
{
n=Read();
siz[1]=1;
lazy[1]=-1;
for(int i=1;i<n;i++) x=Read(),x++,siz[i+1]=1,lazy[i+1]=-1,add(x,i+1),add(i+1,x);
m=Read();
dfs1(1,0),dfs2(1,1);
// for(int i=1;i<=n;i++) cout<<siz[i]<<" ";
// cout<<endl;
// for(int i=1;i<=n;i++) cout<<id[i]<<" ";
for(int i=1;i<=m;i++)
{
cin>>saber;
x=Read();
x++;
if(saber[0]=='i')
{
ans=dep[x]-queryR(1,x);
updateR(1,x,1);
printf("%d\n",ans);
}
if(saber[0]=='u')
{;
ans=queryT(x);
updateT(x,0);
printf("%d\n",ans);
}
}
return 0;
}