[LCT]luogu P3203 弹飞绵羊
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; } } } }
在日渐沉没的世界里,我发现了你。