LCT板子
用一个$p[i]$数组维护每个点指向的下个点。
每次修改时cut*1+link*1就解决了
被弹出界时新设一个点,权为0,作为终点表示出界点。其他点点权为1。
然后统计一下路径就好辣
注意点的编号从0开始
#include<cstdio>
inline void Swap(int &a,int &b){a^=b^=a^=b;}
#define N 200005
int n,m,ch[N][],fa[N],s[N],rev[N],p[N];
#define lc ch[x][0]
#define rc ch[x][1]
inline bool nrt(int x){return ch[fa[x]][]==x||ch[fa[x]][]==x;}
inline void up(int x){s[x]=s[lc]+s[rc]+;}
inline void Rev(int x){Swap(lc,rc);rev[x]^=;}
inline void down(int x){if(rev[x]) Rev(lc),Rev(rc),rev[x]=;}
void pre(int x){if(nrt(x))pre(fa[x]); down(x);}
void turn(int x){
int y=fa[x],z=fa[y],l=(ch[y][]==x),r=l^;
if(nrt(y)) ch[z][ch[z][]==y]=x;
fa[ch[x][r]]=y ;fa[y]=x; fa[x]=z;
ch[y][l]=ch[x][r]; ch[x][r]=y;
up(y); up(x);
}
inline void splay(int x){
pre(x);
for(;nrt(x);turn(x)){
int y=fa[x],z=fa[y];
if(nrt(y)) turn(((ch[y][]==x)^(ch[z][]==y))?x:y);
}
}
inline void access(int x){for(int y=;x;y=x,x=fa[x])splay(x),rc=y,up(x);}
inline void makert(int x){access(x);splay(x);Rev(x);}
inline int find(int x){
access(x);splay(x);down(x);
while(lc) x=lc,down(x);
splay(x); return x;
}
inline void link(int x,int y){makert(x); if(find(y)!=x)fa[x]=y;}
inline void cut(int x,int y){
makert(x);
if(find(y)==x&&fa[y]==x&&!ch[y][]) fa[y]=rc=,up(x);
}
inline void split(int x,int y){makert(x);access(y);splay(y);}
int main(){
scanf("%d",&n); int q1,q2,q3;
for(int i=;i<=n;++i){
scanf("%d",&p[i]);
p[i]=p[i]+i>n ? n+:p[i]+i;
link(i,p[i]);
}
scanf("%d",&m);
while(m--){
scanf("%d%d",&q1,&q2);++q2;
if(q1==) split(n+,q2),printf("%d\n",s[q2]-);
else{
cut(q2,p[q2]);
scanf("%d",&q3);
p[q2]=q2+q3>n?n+:q2+q3;
link(q2,p[q2]);
}
}return ;
}