熟练剖分
路径到根直接向上跳
#include <iostream>
#include <cassert>
#include <string>
using namespace std;
const int MAXN=101111;
int N, M;
int P;
string com;
struct Vert{
int Fa, Son, Bro;
int Size, Dep;
int MainSon, Top;
int Dps, Dpr;
} V[MAXN];
void DFS1(int at){
V[at].Size=1;
for(int to=V[at].Son;to>0;to=V[to].Bro){
V[to].Dep=V[at].Dep+1;
DFS1(to);
V[at].Size+=V[to].Size;
if(V[at].MainSon<=0 || V[to].Size>V[V[at].MainSon].Size) V[at].MainSon=to;
}
}
int Dfn[MAXN], DFN;
void DFS2(int at, int t){
++DFN;
Dfn[DFN]=at;V[at].Dps=DFN;
V[at].Top=t;
if(V[at].MainSon>0) DFS2(V[at].MainSon, t);
for(int to=V[at].Son;to>0;to=V[to].Bro){
if(to==V[at].MainSon) continue;
DFS2(to, to);
}
V[at].Dpr=DFN;/**/
}
struct Node{
int l, r;
int Sum;
int opt;
} T[MAXN<<2];
int L, R, op;
int Sum;
void BuildTree(int l, int r, int at){
T[at].l=l;T[at].r=r;T[at].Sum=0;T[at].opt=-1;
if(l<r){
int m=(l+r)>>1;
BuildTree(l, m, at<<1);
BuildTree(m+1, r, (at<<1)|1);
}
}
void opr(int at){
T[at].Sum=op*(T[at].r-T[at].l+1);
}
void cop(int at){
T[at].opt=op;
}
void pdw(int at){
if(T[at].opt==-1) return;
int top=op;op=T[at].opt;
opr(at<<1);cop(at<<1);
opr((at<<1)|1);cop((at<<1)|1);
op=top;T[at].opt=-1;
}
void pup(int at){
T[at].Sum=T[at<<1].Sum+T[(at<<1)|1].Sum;
}
int Ask(int at){
if(T[at].l>=L && T[at].r<=R){
return T[at].Sum;
}
pdw(at);
int m=(T[at].l+T[at].r)>>1;
int ret=0;
if(L<=m) ret+=Ask(at<<1);
if(R>m) ret+=Ask((at<<1)|1);
return ret;
}
void Update(int at){
if(T[at].l>=L && T[at].r<=R){
T[at].Sum=op*(T[at].r-T[at].l+1);
T[at].opt=op;
return;
}
pdw(at);
int m=(T[at].l+T[at].r)>>1;
if(L<=m) Update(at<<1);
if(R>m) Update((at<<1)|1);
pup(at);
}
int main(){
ios_base::sync_with_stdio(false);
cin >> N;
for(int i=2, f;i<=N;++i){
cin >> f;++f;
V[i].Fa=f;V[i].Bro=V[f].Son;V[f].Son=i;
}
V[1].Dep=1;
DFS1(1);
DFS2(1, 1);
assert(DFN==N);
BuildTree(1, N, 1);
cin >> M;
while(M--){
cin >> com >> P;++P;
Sum=0;
if(com[0]=='i'){
op=1;
for(int k=P;k>0;k=V[V[k].Top].Fa){
L=V[V[k].Top].Dps;R=V[k].Dps;
Sum+=Ask(1);
Update(1);
}
cout << V[P].Dep-Sum << endl;
}
else{
op=0;
L=V[P].Dps;R=V[P].Dpr;
Sum=Ask(1);
Update(1);
cout << Sum << endl;
}
}
return 0;
}