Bzoj2002 [Hnoi2010]Bounce 弹飞绵羊
Submit: 9355 Solved: 4816
Description
某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞。绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞。为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数。
Input
第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000
Output
对于每个i=1的情况,你都要输出一个需要的步数,占一行。
Sample Input
4
1 2 1 1
3
1 1
2 1 1
1 1
1 2 1 1
3
1 1
2 1 1
1 1
Sample Output
2
3
3
HINT
Source
树 LCT
每个位置当成一个结点,维护一棵Link-cut tree
将代表出界的点0置为根。如果一个点x可以弹跳到另一个点y,就连接x和y;如果从x会弹飞,就连接x和0
回答询问时,先access(x),看x左子树的size(也就是x的father的数量)就知道需要弹多少次了。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int mxn=200010; 8 int read(){ 9 int x=0,f=1;char ch=getchar(); 10 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();} 12 return x*f; 13 } 14 int n,m; 15 struct node{ 16 int ch[2]; 17 int sz,fa; 18 bool rt; 19 }t[mxn]; 20 void init(){ 21 for(int i=1;i<=n;i++){t[i].sz=1;t[i].rt=1;} 22 return; 23 } 24 void pushup(int rt){ 25 t[rt].sz=t[t[rt].ch[0]].sz+t[t[rt].ch[1]].sz+1; 26 return; 27 } 28 void rotate(int x){ 29 int y=t[x].fa;int z=t[y].fa,lc,rc; 30 if(t[y].ch[0]==x)lc=0;else lc=1; rc=lc^1; 31 if(t[y].rt){ 32 t[y].rt=0;t[x].rt=1; 33 } 34 else t[z].ch[t[z].ch[1]==y]=x; 35 t[x].fa=z;t[y].ch[lc]=t[x].ch[rc]; 36 t[t[x].ch[rc]].fa=y;t[x].ch[rc]=y; 37 t[y].fa=x; 38 pushup(y); 39 return; 40 } 41 void Splay(int x){ 42 while(!t[x].rt){ 43 int y=t[x].fa;int z=t[y].fa; 44 if(t[y].rt)rotate(x); 45 else{ 46 if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(x); 47 else rotate(y); 48 rotate(x); 49 } 50 } 51 pushup(x); 52 return; 53 } 54 void access(int x){//访问x 55 int y=0; 56 while(x){ 57 Splay(x); 58 t[t[x].ch[1]].rt=1;t[y].rt=0;//切断x原来的右子树 59 t[x].ch[1]=y;//当前点连接被访问点 60 pushup(x); 61 y=x;x=t[x].fa;//上溯 62 } 63 } 64 void find(int x){ 65 access(x); 66 Splay(x); 67 } 68 void link(int x,int y){ 69 find(x); 70 t[t[x].ch[0]].fa=0; 71 t[t[x].ch[0]].rt=1; 72 t[x].ch[0]=0; 73 t[x].fa=y; 74 pushup(x); 75 return; 76 } 77 int main(){ 78 int i,j,k,u,v; 79 n=read(); 80 init(); 81 for(i=1;i<=n;i++){ 82 k=read(); 83 if(i+k<=n)link(i,i+k); 84 } 85 m=read(); 86 while(m--){ 87 k=read(); 88 if(k==1){ 89 u=read()+1;//编号整体+1 90 find(u); 91 printf("%d\n",t[t[u].ch[0]].sz+1); 92 } 93 else{ 94 u=read()+1;k=read(); 95 if(u+k>n)link(u,0); 96 else link(u,u+k); 97 } 98 } 99 return 0; 100 }
本文为博主原创文章,转载请注明出处。