[BZOJ 2002] 弹飞绵羊 LCT
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 2002] 弹飞绵羊 LCT相关的知识,希望对你有一定的参考价值。
题意
给定 n 个装置, 每个装置有系数 K[i] .
在点 i 的绵羊会被弹到 i + K[i] , 如果 i + K[i] > n , 则定义为被弹飞.
m 次操作, 每次操作是下面的某种:
① 更改某个装置的系数 K[x] = y .
② 问一只从装置 x 出发的绵羊几次被弹飞.
n <= 200000 .
实现
1. 不需要换根.
2. par[x] 指当前子树中深度最小的点的父亲.
c[x][0] 的子树指深度比当前点小的一些祖先.
c[x][1] 的子树指深度比当前点大的一条后继.
这样理解会比 [ 肤浅地认为是 Splay 的相关信息 ] 要好.
3. Expose(x)
Splay(x) , c[x][1] = t, Up(x), t = x, x = par[x] .
用 2. 解释 c[x][1] = t .
4. Link(x, y)
Splay(x), par[x] = y .
5. Cut(x, y)
Expose(x), Splay(x), par[c[x][0]] = 0, c[x][0] = 0, Up(x) .
用 2. 解释后面三个操作.
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cctype> 5 #define F(i, a, b) for (register int i = (a); i <= (b); i++) 6 inline int rd(void) { 7 int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; 8 int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; 9 } 10 11 const int N = 200005; 12 13 int n, K[N]; 14 int par[N], c[N][2], siz[N]; 15 16 inline void Up(int x) { siz[x] = siz[c[x][0]] + siz[c[x][1]] + 1; } 17 18 inline bool Root(int x) { return c[par[x]][0] != x && c[par[x]][1] != x; } 19 inline void Rot(int x) { 20 int t = par[x], z = par[t]; 21 int L = (c[t][1] == x), R = L^1; 22 23 if (!Root(t)) 24 c[z][c[z][1] == t] = x; 25 par[x] = z; 26 27 if (c[x][R] > 0) 28 par[c[x][R]] = t; 29 c[t][L] = c[x][R]; 30 31 c[x][R] = t, par[t] = x; 32 Up(t), Up(x); 33 } 34 inline void Splay(int x) { 35 for (; !Root(x); Rot(x)) { 36 int y = par[x], z = par[y]; 37 if (!Root(y)) 38 (c[y][0] == x) ^ (c[z][0] == y) ? Rot(x) : Rot(y); 39 } 40 } 41 42 inline void Expose(int x) { 43 for (int t = 0; x > 0; t = x, x = par[x]) { 44 Splay(x); 45 c[x][1] = t, Up(x); 46 } 47 } 48 inline void Link(int x, int y) { Splay(x), par[x] = y; } 49 inline void Cut(int x) { 50 Expose(x); 51 Splay(x); 52 par[c[x][0]] = 0, c[x][0] = 0, Up(x); 53 } 54 inline int Query(int x) { 55 Expose(x); 56 Splay(x); 57 return siz[x]; 58 } 59 60 int main(void) { 61 #ifndef ONLINE_JUDGE 62 freopen("xsy2531.in", "r", stdin); 63 #endif 64 65 n = rd(); 66 F(i, 1, n) siz[i] = 1; 67 68 F(i, 1, n) K[i] = rd(); 69 F(i, 1, n) if (i + K[i] <= n) 70 Link(i, i + K[i]); 71 72 int m = rd(); 73 F(i, 1, m) { 74 int k = rd(); 75 if (k == 1) { 76 int x = rd() + 1; 77 printf("%d\n", Query(x)); 78 } 79 else { 80 int x = rd() + 1, y = rd(); 81 if (x + K[x] <= n) Cut(x); 82 K[x] = y; 83 if (x + K[x] <= n) Link(x, x + K[x]); 84 } 85 } 86 87 return 0; 88 }
以上是关于[BZOJ 2002] 弹飞绵羊 LCT的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj2002][Hnoi2010]Bounce弹飞绵羊_LCT
bzoj 2002 : [Hnoi2010]Bounce 弹飞绵羊 (LCT)