BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊
2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 5708 Solved: 3005
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
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 300010; 4 struct LCT{ 5 int fa[maxn],ch[maxn][2],sz[maxn],parent[maxn]; 6 inline void pushup(int x){ 7 sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]]; 8 } 9 void rotate(int x,int kd){ 10 int y = fa[x]; 11 ch[y][kd^1] = ch[x][kd]; 12 fa[ch[x][kd]] = y; 13 fa[x] = fa[y]; 14 ch[x][kd] = y; 15 fa[y] = x; 16 if(fa[x]) ch[fa[x]][y == ch[fa[x]][1]] = x; 17 pushup(y); 18 } 19 void splay(int x,int goal = 0){ 20 int y = x; 21 while(fa[y]) y = fa[y]; 22 if(x != y){ 23 parent[x] = parent[y]; 24 parent[y] = 0; 25 while(fa[x] != goal){ 26 if(fa[fa[x]] == goal) rotate(x,x == ch[fa[x]][0]); 27 else{ 28 int y = fa[x],z = fa[y],s = (ch[z][0] == y); 29 if(x == ch[y][s]){ 30 rotate(x,s^1); 31 rotate(x,s); 32 }else{ 33 rotate(y,s); 34 rotate(x,s); 35 } 36 } 37 } 38 pushup(x); 39 } 40 } 41 void access(int x){ 42 for(int y = 0; x; x = parent[x]){ 43 splay(x); 44 fa[ch[x][1]] = 0; 45 parent[ch[x][1]] = x; 46 ch[x][1] = y; 47 fa[y] = x; 48 parent[y] = 0; 49 y = x; 50 pushup(x); 51 } 52 } 53 void cut(int x){ 54 access(x); 55 splay(x); 56 parent[ch[x][0]] = parent[x]; 57 parent[x] = 0; 58 fa[ch[x][0]] = 0; 59 ch[x][0] = 0; 60 } 61 void join(int x,int y){ 62 cut(x); 63 parent[x] = y; 64 } 65 void init(){ 66 memset(fa,0,sizeof fa); 67 memset(sz,0,sizeof sz); 68 memset(ch,0,sizeof ch); 69 memset(parent,0,sizeof parent); 70 } 71 }lct; 72 int main(){ 73 int n,m,x,y,z,op; 74 while(~scanf("%d",&n)){ 75 lct.init(); 76 for(int i = 1; i <= n; ++i){ 77 scanf("%d",&x); 78 if(i + x > n) lct.parent[i] = 0; 79 else lct.parent[i] = i + x; 80 lct.sz[i] = 1; 81 } 82 scanf("%d",&m); 83 while(m--){ 84 scanf("%d%d",&op,&x); 85 ++x; 86 if(op == 1){ 87 lct.access(x); 88 lct.splay(x); 89 printf("%d\n",lct.sz[lct.ch[x][0]] + 1); 90 }else{ 91 scanf("%d",&y); 92 if(x + y > n) y = 0; 93 else y += x; 94 lct.join(x,y); 95 } 96 } 97 } 98 return 0; 99 }
夜空中最亮的星,照亮我前行