BZOJ_2002_弹飞绵羊_(LCT)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=2002
一列n个数,a[i]表示向后a[i]个,问第k个数进行多少次向后跳跃会飞出去.
分析
i连向i+a[i],那么我们建立一个森林,i是i+a[i]的一个子节点,如果i+a[i]>n,那么i连向null.这样对于节点k,问多少次飞出去,就是向上走多少个到null,也就是深度是多少,直接LCt处理.
注意:
1.这里的link并不以LCT中普遍的link.普通的link是将两个不想连的点连在一起,这样两棵树也就连在了一起.这里的link其实是改变父亲节点的意思.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=200000+5; 5 int n,m; 6 7 struct node{ 8 node* ch[2],* pa; 9 int s; 10 node(node* t){ s=1; ch[0]=ch[1]=pa=t; } 11 bool d(){ return pa->ch[1]==this; } 12 bool c(){ return pa->ch[0]==this||pa->ch[1]==this; } 13 void setc(node* x,bool d){ ch[d]=x; x->pa=this; } 14 void push_up(){ s=ch[0]->s+ch[1]->s+1; } 15 }* null,* t[maxn]; 16 void rot(node* x){ 17 node* pa=x->pa; bool d=x->d(); 18 if(pa->c()) pa->pa->setc(x,pa->d()); 19 else x->pa=pa->pa; 20 pa->setc(x->ch[!d],d); 21 x->setc(pa,!d); 22 pa->push_up(); 23 } 24 void splay(node* x){ 25 while(x->c()) 26 if(!x->pa->c()) rot(x); 27 else x->d()==x->pa->d()?(rot(x->pa),rot(x)):(rot(x),rot(x)); 28 x->push_up(); 29 } 30 void access(node* x){ 31 node* t=x; 32 for(node* y=null;x!=null;y=x, x=x->pa){ 33 splay(x); 34 x->ch[1]=y; 35 } 36 splay(t); 37 } 38 void link(node* x,node* y){ 39 access(x); 40 x->ch[0]->pa=null; x->ch[0]=null; x->pa=y; x->push_up(); 41 } 42 int main(){ 43 null=new node(NULL); null->s=0; 44 scanf("%d",&n); 45 for(int i=0;i<n;i++) t[i]=new node(null); 46 for(int i=0;i<n;i++){ 47 int k; scanf("%d",&k); 48 if(i+k<n) t[i]->pa=t[i+k]; 49 } 50 scanf("%d",&m); 51 for(int i=1;i<=m;i++){ 52 int q,x,y; 53 scanf("%d%d",&q,&x); 54 if(q==1){ 55 access(t[x]); 56 printf("%d\n",t[x]->s); 57 } 58 else{ 59 scanf("%d",&y); 60 if(x+y<n) link(t[x],t[x+y]); 61 else link(t[x],null); 62 } 63 } 64 return 0; 65 }