BZOJ 2002 [HNOI2010]Bounce 弹飞绵羊 - LCT
Solution
只需要支持$access$ , $cut$ 和 $link$就可以了。
注意不要$makeroot$。
查询时查询 根节点的左子树大小 $+ 1$
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 using namespace std; 6 7 const int N = 2e5 + 5; 8 9 int n, m, a[N]; 10 11 int read() { 12 int X = 0, p = 1; char c = getchar(); 13 for (; c > '9' || c < '0'; c = getchar()) 14 if (c == '-') p = -1; 15 for (; c >= '0' && c <= '9'; c = getchar()) 16 X = X * 10 + c - '0'; 17 return X * p; 18 } 19 20 namespace LCT { 21 int f[N], ch[N][2], sum[N], tur[N]; 22 23 #define rc(x) ch[x][1] 24 #define lc(x) ch[x][0] 25 26 int isroot(int x) { 27 return lc(f[x]) != x && rc(f[x]) != x; 28 } 29 30 int get(int x) { 31 return rc(f[x]) == x; 32 } 33 34 void rev(int x) { 35 swap(lc(x), rc(x)); 36 tur[x] ^= 1; 37 } 38 39 void pushdown(int x) { 40 if (tur[x]) { 41 rev(lc(x)); 42 rev(rc(x)); 43 tur[x] = 0; 44 } 45 } 46 47 void pd(int x) { 48 if(!isroot(x)) 49 pd(f[x]); 50 pushdown(x); 51 } 52 53 void up(int x) { 54 sum[x] = sum[lc(x)] + sum[rc(x)] + 1; 55 } 56 57 void rotate(int x) { 58 int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1]; 59 if (!isroot(old)) ch[oldf][get(old)] = x; 60 ch[x][get(x) ^ 1] = old; 61 ch[old][get(x)] = son; 62 f[x] = oldf; f[old] = x; f[son] = old; 63 up(old); up(x); 64 } 65 66 void splay(int x) { 67 pd(x); 68 for(; !isroot(x); rotate(x)) 69 if(!isroot(f[x])) 70 rotate(get(x) == get(f[x]) ? f[x] : x); 71 } 72 73 void access(int x) { 74 for (int y = 0; x; y = x, x = f[x]) 75 splay(x), rc(x) = y, up(x); 76 } 77 78 void mroot(int x) { 79 access(x); splay(x); rev(x); 80 } 81 82 void split(int x, int y) { 83 mroot(x); access(y); splay(y); 84 } 85 86 int findr(int x) { 87 access(x); splay(x); 88 while (lc(x)) pushdown(x), x = lc(x); 89 return x; 90 } 91 92 void link(int x, int y) { 93 if (x > n || y > n) 94 return; 95 access(x); splay(x); 96 f[x] = y; 97 } 98 99 void cut(int x, int y) { 100 if (x > n || y > n) 101 return; 102 access(x); splay(x); 103 access(y); splay(y); 104 f[x] = ch[y][1] = 0; 105 up(y); 106 } 107 108 int query(int x) { 109 access(x); splay(x); 110 if (lc(x)) 111 return sum[lc(x)] + 1; 112 return 1; 113 } 114 } 115 using namespace LCT; 116 117 int main() 118 { 119 n = rd; 120 for (int i = 1; i <= n; ++i) 121 a[i] = rd; 122 for (int i = 1; i <= n; ++i) 123 if (a[i] + i <= n) 124 link(i, a[i] + i); 125 m = rd; 126 for (int i = 1; i <= m; ++i) { 127 int k = rd; 128 if (k == 1) 129 printf("%d\n", query(rd + 1)); 130 else { 131 int u = rd + 1, v = rd; 132 cut(u, u + a[u]); 133 link(u, u + v); 134 a[u] = v; 135 } 136 } 137 }