[BZOJ2002] [Hnoi2010] Bounce 弹飞绵羊 (LCT)
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
Solution
每个点和可以到达的点连一条边,支持动态链上查询,LCT大法好
用和splay一样的方法维护子树大小siz即可。
感谢Ngshily大吔爷的版子!!!
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct LCT 4 { 5 int c[2], fa, rev, siz; 6 int& operator [] (int i) 7 { 8 return c[i]; 9 } 10 }a[200005]; 11 int sta[200005], top, nxt[200005]; 12 13 void scanf(int *x) 14 { 15 char ch = getchar(); 16 *x = 0; 17 while(ch < '0' || ch > '9') 18 ch = getchar(); 19 while(ch >= '0' && ch <= '9') 20 *x = *x * 10 + ch - 48, ch = getchar(); 21 } 22 23 void push_up(int k) 24 { 25 a[k].siz = a[a[k][0]].siz + a[a[k][1]].siz + 1; 26 } 27 28 void push_down(int k) 29 { 30 if(a[k].rev) 31 { 32 a[a[k][0]].rev ^= 1, a[a[k][1]].rev ^= 1; 33 swap(a[k][0], a[k][1]), a[k].rev = 0; 34 } 35 } 36 37 bool isroot(int x) 38 { 39 return a[a[x].fa][0] != x && a[a[x].fa][1] != x; 40 } 41 42 void rotate(int x) 43 { 44 int y = a[x].fa, z = a[y].fa; 45 int dy = a[y][1] == x, dz = a[z][1] == y; 46 if(!isroot(y)) a[z][dz] = x; 47 a[y][dy] = a[x][dy ^ 1], a[a[x][dy ^ 1]].fa = y; 48 a[x][dy ^ 1] = y, a[y].fa = x, a[x].fa = z; 49 push_up(y); 50 } 51 52 void splay(int x) 53 { 54 sta[top = 1] = x; 55 for(int i = x; !isroot(i); i = a[i].fa) 56 sta[++top] = a[i].fa; 57 while(top) 58 push_down(sta[top--]); 59 while(!isroot(x)) 60 { 61 int y = a[x].fa, z = a[y].fa; 62 if(!isroot(y)) 63 if(a[y][1] == x ^ a[z][1] == y) rotate(x); 64 else rotate(y); 65 rotate(x); 66 } 67 push_up(x); 68 } 69 70 void access(int x) 71 { 72 for(int i = 0; x; x = a[x].fa) 73 splay(x), a[x][1] = i, i = x; 74 } 75 76 void make_root(int x) 77 { 78 access(x), splay(x), a[x].rev ^= 1; 79 } 80 81 int find_root(int x) 82 { 83 access(x), splay(x); 84 while(a[x][0]) 85 x = a[x][0]; 86 return x; 87 } 88 89 void link(int x, int y) 90 { 91 make_root(x), a[x].fa = y; 92 } 93 94 void cut(int x, int y) 95 { 96 make_root(x), access(y), splay(y), a[y][0] = a[x].fa = 0; 97 } 98 99 int main() 100 { 101 int n, m, x, y, op; 102 scanf(&n); 103 for(int i = 1; i <= n; i++) 104 { 105 scanf(&x), a[i].siz = 1; 106 a[i].fa = nxt[i] = min(i + x, n + 1); 107 } 108 scanf(&m), a[n + 1].siz = 1; 109 while(m--) 110 { 111 scanf(&op), scanf(&x), x++; 112 if(op == 1) 113 { 114 make_root(n + 1), access(x), splay(x); 115 printf("%d\n", a[x].siz - 1); 116 } 117 else 118 { 119 scanf(&y), cut(nxt[x], x); 120 nxt[x] = min(x + y, n + 1); 121 link(nxt[x], x); 122 } 123 } 124 return 0; 125 }