【题意】
给出n个点,每个点都会指向它后方的一个点,显然最后都指向一个不存在的点。把最后一个点当作根拎起来就是一棵树了。询问中,某一个点指向的点随时会变,显然就是要你支持动态改变树的结构。然后又会不时的询问一个点到根的距离。
【题解】
又是lct裸题,注意 维护splay的信息 和 传递标记。。。。。。
其它的细节网上题解一大堆就不多述了。。。。。。
一开始写lct真的好艰辛。。。
【代码】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> using namespace std; const int N=200005; int size[N],c[N][2],rev[N],fa[N],pre[N],a[N]; int n,x,y,Q; void read(int &x) { x=0;char ch;int sign=1; do{ch=getchar();if(ch=='-')sign*=-1;}while (ch<'0' || ch>'9'); do{x=x*10+ch-48;ch=getchar();}while (ch>='0' && ch<='9'); x*=sign; } bool isroot(int x) { return c[fa[x]][0]!=x && c[fa[x]][1]!=x; } void up(int x) { size[x]=size[c[x][0]]+size[c[x][1]]+1; } void down(int x) { if (rev[x]) { rev[x]=0; swap(c[x][0],c[x][1]); rev[c[x][0]]^=1,rev[c[x][1]]^=1; } } void rotate(int x) { int y=fa[x],z=fa[y],l,r; if (c[y][0]==x) l=0;else l=1;r=1^l; if (!isroot(y)) if (c[z][0]==y) c[z][0]=x;else c[z][1]=x; fa[x]=z; c[y][l]=c[x][r];fa[c[x][r]]=y; c[x][r]=y;fa[y]=x; up(y);up(x); } void splay(int x) { int cnt=0,y=x,z; while (!isroot(y)) { a[++cnt]=y; y=fa[y]; } a[++cnt]=y; while (cnt--) down(a[cnt+1]); while (!isroot(x)) { y=fa[x];z=fa[y]; if (!isroot(y)) if (c[y][0]==x ^ c[z][0]==y) rotate(x); else rotate(y); rotate(x); } } void access(int x) { int t=0; while (x) { splay(x); c[x][1]=t; t=x;x=fa[x]; } } void mt(int x) { access(x); splay(x); } void make_root(int x) { mt(x); rev[x]^=1; down(x); } void link(int x,int y) { make_root(x); fa[x]=y; } void cut(int x,int y) { make_root(x); mt(y); fa[x]=c[y][0]=0; up(y); } int solve(int x) { make_root(n+1); mt(x); return size[c[x][0]]; } int main() { read(n); for (int i=1;i<=n;++i) { size[i]=1; read(pre[i]); pre[i]+=i; if (pre[i]>n) pre[i]=n+1; link(i,pre[i]); } read(Q); while (Q--) { read(x); if (x==1) { read(y); ++y; printf("%d\n",solve(y)); } else { read(x);read(y); ++x; cut(x,pre[x]); y=x+y; if (y>n) y=n+1; link(x,pre[x]=y); } } return 0; }