I used to solve this problem in blocks before, but recently I learned LCT, and found that it is also a template problem of LCT, so I did it with LCT.
Block solution: https://blog.csdn.net/f2935552941/article/details/78157052
For LCT, I recommend a blog, which is clear, but if you want to know more about it, you can find the paper of the national training team.
Recommended blog: https://blog.csdn.net/JeremyGJY/article/details/51078087
Solutions:
The specific problem is that we build a n edge for X and x+a[x]. If x+a[x] is greater than N, we can build it to n+1 by default. Then we query the number of times x jumps out, that is, we can pick out the chain from x to n+1, and the number of nodes on the chain is - 1.
If you want to modify it, you can use the normal edge deletion and edge creation,
I found a board of the big guy. I feel it's pretty good.
Ac Code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+10; const int mod=1e9+7; const int INF=1e9+7; ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} int n,m,a[maxn]; struct LCT //LCT template { int father[maxn+5],son[maxn+5][2],si[maxn+5]; bool flip[maxn+5]; void init(){ for(int i=1;i<=n+1;i++) si[i]=1; } void Pushup(int p) {si[p]=si[son[p][0]]+1+si[son[p][1]];} void Add_flip(int p) {swap(son[p][0],son[p][1]);flip[p]^=1;} void Pushdown(int p) { if (!flip[p]) return; if (son[p][0]) Add_flip(son[p][0]); if (son[p][1]) Add_flip(son[p][1]); flip[p]=false; } bool is_ro(int p) {return p!=son[father[p]][0]&&p!=son[father[p]][1];} void Rotate(int p) { int fa=father[p],d=p==son[fa][0]; if (!is_ro(fa)) son[father[fa]][fa==son[father[fa]][1]]=p; son[fa][d^1]=son[p][d];father[son[p][d]]=fa;son[p][d]=fa; Pushup(fa);Pushup(p);father[p]=father[fa];father[fa]=p; } int top,stk[maxn+5]; void Splay(int p) { stk[++top]=p; for (int i=p;!is_ro(i);i=father[i]) stk[++top]=father[i]; while (top) Pushdown(stk[top--]); while (!is_ro(p)) { int fa=father[p]; if (!is_ro(fa)) { int d1=fa==son[father[fa]][1],d2=p==son[fa][1]; if (d1==d2) Rotate(fa); else Rotate(p); } Rotate(p); } } void Access(int p) { int lst=0; while (p) { Splay(p);son[p][1]=lst;Pushup(p); lst=p;p=father[p]; } } void make_ro(int p) {Access(p);Splay(p);Add_flip(p);} void Link(int x,int y) {Access(y);make_ro(y);father[y]=x;} void Cut(int x,int y) { make_ro(y);Access(x);Splay(x); father[y]=son[x][0]=0;Pushup(x); } }; LCT tr; int main() { scanf("%d",&n); tr.init(); //Initialization for(int i=1;i<=n;i++) scanf("%d",&a[i]),tr.Link(min(i+a[i],n+1),i); //Build edge scanf("%d",&m); while(m--) { int flag,x,y; scanf("%d",&flag); if(flag==1) { scanf("%d",&x); x++; tr.make_ro(n+1);tr.Access(x);tr.Splay(x); printf("%d\n",tr.si[x]-1); } else { scanf("%d%d",&x,&y); x++; tr.Cut(min(x+a[x],n+1),x),tr.Link(min(x+y,n+1),x); a[x]=y; } } //system("pause"); return 0; }