1. 程式人生 > >[luoguP3203][HNOI2010]BOUNCE 彈飛綿羊(LCT)

[luoguP3203][HNOI2010]BOUNCE 彈飛綿羊(LCT)

pla color pen log blank += onclick show ++

傳送門

每個點都會跳到另一個點,連邊就是一棵樹。

更改彈力就是換邊。

求一個點跳多少次跳到終點就是求這個點的深度,那麽只需要維護 size 域,access(n + 1) 然後 splay(x),求 size[son[x][0]] 即可,

因為 splay 是以深度為關鍵字的,所以左端點就是深度比它小的。

——代碼

技術分享
  1 #include <cstdio>
  2 #include <iostream>
  3 #define N 200010
  4 #define min(x, y) ((x) < (y) ? (x) : (y))
  5
#define max(x, y) ((x) > (y) ? (x) : (y)) 6 #define swap(x, y) ((x) ^= (y) ^= (x) ^= (y)) 7 #define get(x) (son[f[x]][1] == (x)) 8 #define isroot(x) (son[f[x]][0] ^ (x) && son[f[x]][1] ^ (x)) 9 10 int n, k; 11 int a[N], f[N], size[N], rev[N], son[N][2], s[N]; 12 13 inline int
read() 14 { 15 int x = 0, f = 1; 16 char ch = getchar(); 17 for(; !isdigit(ch); ch = getchar()) if(ch == -) f = -1; 18 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - 0; 19 return x * f; 20 } 21 22 inline void update(int x) 23 {
24 if(x) 25 { 26 size[x] = 1; 27 if(son[x][0]) size[x] += size[son[x][0]]; 28 if(son[x][1]) size[x] += size[son[x][1]]; 29 } 30 } 31 32 inline void pushdown(int x) 33 { 34 if(x && rev[x]) 35 { 36 swap(son[x][0], son[x][1]); 37 if(son[x][0]) rev[son[x][0]] ^= 1; 38 if(son[x][1]) rev[son[x][1]] ^= 1; 39 rev[x] = 0; 40 } 41 } 42 43 inline void rotate(int x) 44 { 45 int old = f[x], oldf = f[old], wh = get(x); 46 47 if(!isroot(old)) 48 son[oldf][old == son[oldf][1]] = x; 49 f[x] = oldf; 50 51 son[old][wh] = son[x][wh ^ 1]; 52 f[son[old][wh]] = old; 53 54 son[x][wh ^ 1] = old; 55 f[old] = x; 56 57 update(old); 58 update(x); 59 } 60 61 inline void splay(int x) 62 { 63 int i, fa, t = 0; 64 s[++t] = x; 65 for(i = x; !isroot(i); i = f[i]) s[++t] = f[i]; 66 for(i = t; i >= 1; i--) pushdown(s[i]); 67 for(; !isroot(x); rotate(x)) 68 if(!isroot(fa = f[x])) 69 rotate(get(x) ^ get(fa) ? x : fa); 70 } 71 72 inline void access(int x) 73 { 74 for(int t = 0; x; t = x, x = f[x]) splay(x), son[x][1] = t, update(x); 75 } 76 77 inline void reverse(int x) 78 { 79 access(x); 80 splay(x); 81 rev[x] ^= 1; 82 } 83 84 inline void cut(int x, int y) 85 { 86 reverse(x); 87 access(y); 88 splay(y); 89 son[y][0] = f[x] = 0; 90 update(y); 91 } 92 93 inline void link(int x, int y) 94 { 95 reverse(x); 96 f[x] = y; 97 access(x); 98 } 99 100 inline int query(int x) 101 { 102 reverse(n + 1); 103 access(x); 104 splay(x); 105 return size[son[x][0]]; 106 } 107 108 int main() 109 { 110 int i, x, y, z; 111 n = read(); 112 for(i = 1; i <= n; i++) 113 { 114 x = read(); 115 a[i] = f[i] = min(i + x, n + 1); 116 size[i] = 1; 117 } 118 size[n + 1] = 1; 119 k = read(); 120 for(i = 1; i <= k; i++) 121 { 122 z = read(); 123 x = read() + 1; 124 if(z == 1) printf("%d\n", query(x)); 125 else 126 { 127 y = read(); 128 cut(x, a[x]); 129 link(x, a[x] = min(x + y, n + 1)); 130 } 131 } 132 return 0; 133 }
View Code

[luoguP3203][HNOI2010]BOUNCE 彈飛綿羊(LCT)