2002: [Hnoi2010]Bounce 弹飞绵羊
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 9071 Solved: 4652
[Submit][Status][Discuss]
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模板题,第一次写还有些许不懂,大体是从这位前辈的blog里学的。
1 VAR 2 n : longint; 3 m : longint; 4 siz : array[-1..200005] of longint; 5 fat : array[-1..200005] of longint; 6 rot : array[-1..200005] of boolean; 7 son : array[-1..200005,0..2] of longint; 8 9 PROCEDURE update(t : longint); 10 begin 11 siz[t]:=siz[son[t,0]]+siz[son[t,1]]+1; 12 end; 13 14 PROCEDURE ltrotate(x : longint); 15 var 16 y : longint; 17 begin 18 y:=son[x,1]; 19 son[x,1]:=son[y,0]; 20 fat[son[x,1]]:=x; 21 son[y,0]:=x; 22 if x=son[fat[x],0] then 23 son[fat[x],0]:=y 24 else if x=son[fat[x],1] then 25 son[fat[x],1]:=y; 26 fat[y]:=fat[x]; 27 fat[x]:=y; 28 rot[y]:=rot[x] xor rot[y]; 29 rot[x]:=rot[x] xor rot[y]; 30 update(x); 31 update(y); 32 end; 33 34 PROCEDURE rtrotate(x : longint); 35 var 36 y : longint; 37 begin 38 y:=son[x,0]; 39 son[x,0]:=son[y,1]; 40 fat[son[x,0]]:=x; 41 son[y,1]:=x; 42 if x=son[fat[x],0] then 43 son[fat[x],0]:=y 44 else if x=son[fat[x],1] then 45 son[fat[x],1]:=y; 46 fat[y]:=fat[x]; 47 fat[x]:=y; 48 rot[y]:=rot[x] xor rot[y]; 49 rot[x]:=rot[x] xor rot[y]; 50 update(x); 51 update(y); 52 end; 53 54 PROCEDURE splay(x : longint); 55 begin 56 while not rot[x] do 57 if x=son[fat[x],1] then 58 ltrotate(fat[x]) 59 else 60 rtrotate(fat[x]); 61 end; 62 63 PROCEDURE access(x : longint); 64 var 65 y : longint; 66 begin 67 splay(x); 68 while fat[x]<>0 do 69 begin 70 y:=fat[x]; 71 splay(y); 72 rot[son[y,1]]:=true; 73 rot[x]:=false; 74 son[y,1]:=x; 75 update(y); 76 splay(x); 77 end; 78 end; 79 80 PROCEDURE main; 81 var 82 i, x, y, z : longint; 83 begin 84 read(n); 85 86 for i:=1 to n do 87 begin 88 read(fat[i]); 89 fat[i]:=fat[i]+i; 90 if fat[i]>n then 91 fat[i]:=n+1; 92 end; 93 94 for i:=1 to n+1 do 95 begin 96 siz[i]:=1; 97 rot[i]:=true; 98 end; 99 100 read(m); 101 102 for i:=1 to m do 103 begin 104 read(x); 105 if x=1 then 106 begin 107 read(y); 108 inc(y); 109 access(y); 110 writeln(siz[son[y,0]]); 111 end 112 else 113 begin 114 read(y,z); 115 inc(y); 116 splay(y); 117 fat[son[y,0]]:=fat[y]; 118 rot[son[y,0]]:=true; 119 son[y,0]:=0; 120 siz[y]:=siz[son[y,1]]+1; 121 fat[y]:=y+z; 122 if fat[y]>n then 123 fat[y]:=n+1; 124 end; 125 end; 126 end; 127 128 BEGIN 129 main; 130 END.
1 #include <bits/stdc++.h> 2 3 #define fread_siz 1024 4 5 inline int get_c(void) 6 { 7 static char buf[fread_siz]; 8 static char *head = buf + fread_siz; 9 static char *tail = buf + fread_siz; 10 11 if (head == tail) 12 fread(head = buf, 1, fread_siz, stdin); 13 14 return *head++; 15 } 16 17 inline int get_i(void) 18 { 19 register int ret = 0; 20 register int neg = false; 21 register int bit = get_c(); 22 23 for (; bit < 48; bit = get_c()) 24 if (bit == '-')neg ^= true; 25 26 for (; bit > 47; bit = get_c()) 27 ret = ret * 10 + bit - 48; 28 29 return neg ? -ret : ret; 30 } 31 32 template <class T> 33 inline T min(T a, T b) 34 { 35 return a < b ? a : b; 36 } 37 38 const int N = 200005; 39 40 int n, m; 41 int root[N]; 42 int lson[N]; 43 int rson[N]; 44 int size[N]; 45 int father[N]; 46 47 inline void update(int t) 48 { 49 size[t] = size[lson[t]] + size[rson[t]] + 1; 50 } 51 52 inline void rotateLeft(int t) 53 { 54 int r = rson[t]; 55 rson[t] = lson[r]; 56 father[rson[t]] = t; 57 lson[r] = t; 58 if (t == lson[father[t]]) 59 lson[father[t]] = r; 60 else if (t == rson[father[t]]) 61 rson[father[t]] = r; 62 father[r] = father[t]; 63 father[t] = r; 64 update(t); 65 update(r); 66 root[r] ^= root[t]; 67 root[t] ^= root[r]; 68 } 69 70 inline void rotateRight(int t) 71 { 72 int l = lson[t]; 73 lson[t] = rson[l]; 74 father[lson[t]] = t; 75 rson[l] = t; 76 if (t == lson[father[t]]) 77 lson[father[t]] = l; 78 else if (t == rson[father[t]]) 79 rson[father[t]] = l; 80 father[l] = father[t]; 81 father[t] = l; 82 update(t); 83 update(l); 84 root[l] ^= root[t]; 85 root[t] ^= root[l]; 86 } 87 88 inline void splay(int t) 89 { 90 while (!root[t]) 91 { 92 if (t == lson[father[t]]) 93 rotateRight(father[t]); 94 else 95 rotateLeft(father[t]); 96 } 97 } 98 99 inline void access(int t) 100 { 101 splay(t); 102 103 while (father[t]) 104 { 105 int f = father[t]; 106 splay(f); 107 root[rson[f]] = 1; 108 root[t] = 0; 109 rson[f] = t; 110 update(f); 111 splay(t); 112 } 113 } 114 115 inline void cut(int t) 116 { 117 splay(t); 118 root[lson[t]] = 1; 119 father[lson[t]] = father[t]; 120 lson[t] = 0; 121 update(t); 122 } 123 124 signed main(void) 125 { 126 n = get_i(); 127 128 for (int i = 1; i <= n; ++i) 129 father[i] = min(get_i() + i, n + 1); 130 131 for (int i = 1; i <= n + 1; ++i) 132 size[i] = root[i] = 1; 133 134 m = get_i(); 135 136 for (int i = 1; i <= m; ++i) 137 { 138 int x = get_i(), y, z; 139 if (x == 1) 140 { 141 y = get_i() + 1; access(y); 142 printf("%d ", size[lson[y]]); 143 } 144 else 145 { 146 y = get_i() + 1; z = get_i(); 147 cut(y); father[y] = min(n + 1, y + z); 148 } 149 } 150 }
@Author: YouSiki