bzoj2002 弹飞绵羊 lct版
这道题就是维护一个有根的lct 一开始建树全部建虚边 求多少次弹出就是求他到根的距离(根为n+1)
这里有个小技巧 将n+1作为根而没有虚根操作起来会比较方便
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=200007; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } int n,m,c[M][2],size[M],fa[M]; bool isrt(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 rotate(int x){ int y=fa[x],z=fa[y],l=0,r=1; if(c[y][1]==x) l=1,r=0; if(!isrt(y)) c[z][c[z][1]==y]=x; fa[y]=x; fa[x]=z; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; up(y); up(x); } void splay(int x){ while(!isrt(x)){ int y=fa[x],z=fa[y]; if(!isrt(y)){ if(c[z][0]==y^c[y][0]==x) rotate(x); else rotate(y); } rotate(x); } } void acs(int x){ int t=0,y=x; while(x){ splay(x); c[x][1]=t; up(x); t=x; x=fa[x]; } splay(y); } void cut_link(int x,int y){ acs(x); fa[c[x][0]]=0; c[x][0]=0; fa[x]=min(y+x,n+1); } int push_ans(int x){acs(x); return size[x]-1;} int main() { int x,y; n=read(); for(int i=1;i<=n+1;i++) size[i]=1; for(int i=1;i<=n;i++) y=read(),fa[i]=min(i+y,n+1); m=read(); while(m--){ if(read()==1) x=read()+1,printf("%d\n",push_ans(x)); else x=read()+1,y=read(),cut_link(x,y); } return 0; }