【题解】
这道题可以用Link-Cut Tree写。。
首先建立一个虚拟节点N+1,$i$与$N+1$连边表示$i$被弹飞了
对于修改操作,先$cut(i,min(n+1,i+k[i]))$,然后再$link(i,min(n+1,i+newk))$
对于询问操作,先$makeroot(x)$,然后$splay(n+1)$,$access(n+1)$,那么答案就是$size[n+1]-1$
1 #include<cstdio> 2 #include<algorithm> 3 #define N (500010) 4 #define ls (c[u][0]) 5 #define rs (c[u][1]) 6 using namespace std; 7 int n,m,opt,k[N]; 8 inline int read(){ 9 int k=0,f=1; char c=getchar(); 10 while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); 11 while(‘0‘<=c&&c<=‘9‘)k=k*10+c-‘0‘,c=getchar(); 12 return k*f; 13 } 14 struct Link_Cut_Tree{ 15 int top,c[N][2],fa[N],rev[N],size[N],q[N]; 16 inline void pushdown(int u){ 17 if(rev[u]) rev[ls]^=1,rev[rs]^=1,rev[u]^=1,swap(ls,rs); 18 } 19 inline void pushup(int u){ 20 size[u]=1; 21 if(ls) size[u]+=size[ls]; 22 if(rs) size[u]+=size[rs]; 23 } 24 inline bool isroot(int u){ 25 return c[fa[u]][0]!=u&&c[fa[u]][1]!=u; 26 } 27 inline bool which(int u){ 28 return c[fa[u]][1]==u; 29 } 30 void rotate(int u){ 31 int f=fa[u],gf=fa[f],wh=which(u); 32 if(!isroot(f)) c[gf][which(f)]=u; 33 fa[u]=gf; fa[f]=u; fa[c[u][wh^1]]=f; 34 c[f][wh]=c[u][wh^1]; c[u][wh^1]=f; 35 pushup(f); pushup(u); 36 } 37 void splay(int u){ 38 q[top=1]=u; 39 for(int i=u;!isroot(i);i=fa[i]) q[++top]=fa[i]; 40 for(int i=top;i;i--) pushdown(q[i]); 41 while(!isroot(u)){ 42 if(!isroot(fa[u])) rotate(which(u)==which(fa[u])?fa[u]:u); 43 rotate(u); 44 } 45 pushup(u); 46 } 47 void access(int u){ 48 for(int son=0;u;son=u,u=fa[u]) 49 splay(u),c[u][1]=son,pushup(u); 50 } 51 void makeroot(int u){ 52 access(u); splay(u); rev[u]^=1; 53 } 54 int find(int u){ 55 access(u); splay(u); 56 while(ls) u=ls; splay(u); 57 return u; 58 } 59 void split(int x,int y){ 60 makeroot(x); access(y); splay(y); 61 } 62 void cut(int x,int y){ 63 int xrt=find(x),yrt=find(y); 64 if(xrt!=yrt) return; 65 split(x,y); 66 if(c[y][0]==x) c[y][0]=0,fa[x]=0; 67 pushup(y); 68 } 69 void link(int x,int y){ 70 int xrt=find(x),yrt=find(y); 71 if(xrt==yrt) return; 72 makeroot(x); fa[x]=y; 73 } 74 }t; 75 int main(){ 76 n=read(); 77 for(int i=1;i<=n;i++) t.link(i,min(n+1,i+(k[i]=read()))); 78 m=read(); 79 while(m--){ 80 if((opt=read())==1){ 81 int x=read()+1; 82 t.makeroot(x); t.access(n+1); t.splay(n+1); 83 printf("%d\n",t.size[n+1]-1); 84 } 85 else{ 86 int x=read()+1,y=read(); 87 if(x+y>n+1&&x+k[x]>n+1) continue; 88 t.cut(x,min(n+1,x+k[x])); 89 t.link(x,min(n+1,x+y)); 90 k[x]=y; 91 } 92 } 93 return 0; 94 }