https://www.luogu.org/problem/P3203
分析
还有个模板不想写题解了,反正这题也差不多是个模板
可以将一个点往后跳跃到的点连起来,跳出去的连到根节点+1,这就是棵树
要求支持删边连边和求根节点到这里的深度?LCT完全可以胜任
就是个板子,深度不用特别思考,Split直接提出来的是链,求Splay大小即可

#include <iostream>
#include <cstdio>
using namespace std;
const int N=2e5+10;
struct Node {
int f,c[2],s,rev;
}t[N];
int stk[N],top,v[N];
int n,m;
bool Witch(int x) {return x==t[t[x].f].c[1];}
bool Check_Root(int x) {return t[t[x].f].c[0]==x||t[t[x].f].c[1]==x;}
void Reverse(int x) {swap(t[x].c[0],t[x].c[1]),t[x].rev^=1;}
void Pushdown(int x) {if (t[x].rev) Reverse(t[x].c[0]),Reverse(t[x].c[1]),t[x].rev=0;}
void Update(int x) {t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+1;}
void Rotate(int x) {
int f=t[x].f,gf=t[f].f,lr=Witch(x);
t[x].f=gf;if (Check_Root(f)) t[gf].c[Witch(f)]=x;
t[f].c[lr]=t[x].c[lr^1];if (t[f].c[lr]) t[t[f].c[lr]].f=f;
t[t[x].c[lr^1]=f].f=x;
Update(f);
}
void Splay(int x) {
int y=x;stk[++top]=y;
for (;Check_Root(y);y=t[y].f) stk[++top]=t[y].f;
for (;top;Pushdown(stk[top--]));
for (;Check_Root(x);Rotate(x))
if (Check_Root(t[x].f)) Rotate(Witch(x)!=Witch(t[x].f)?x:t[x].f);
Update(x);
}
void Access(int x) {for (int y=0;x;x=t[y=x].f) Splay(x),t[x].c[1]=y,Update(x);}
void Make_Root(int x) {Access(x);Splay(x);Reverse(x);}
int Get_Root(int x) {
Make_Root(x);Splay(x);
while (t[x].c[0]) x=t[x].c[0],Pushdown(x);
Splay(x);return x;
}
void Split(int x,int y) {Make_Root(x);Access(y);Splay(y);}
void Link(int x,int y) {Make_Root(x);if (Get_Root(y)!=x) t[x].f=y;}
void Cut(int x,int y) {Split(x,y);if (t[y].c[0]==x) t[x].f=t[y].c[0]=0,Update(y);}
int main() {
scanf("%d",&n);
for (int i=1,x;i<=n;i++) {
scanf("%d",&x);
v[i]=min(i+x,n+1);
Link(i,v[i]);
}
scanf("%d",&m);
for (int i=1;i<=m;i++) {
int order,x,y;
scanf("%d",&order);
switch (order) {
case 1:{
scanf("%d",&x);x++;
Split(x,n+1);printf("%d\n",t[n+1].s-1);
break;
}
case 2:{
scanf("%d%d",&x,&y);x++;
if (v[x]==min(x+y,n+1)) continue;
Cut(x,v[x]);Link(x,v[x]=min(x+y,n+1));
break;
}
}
}
}
