[luoguP3203][HNOI2010]BOUNCE 弹飞绵羊(LCT)

Posted 蒟蒻zht的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[luoguP3203][HNOI2010]BOUNCE 弹飞绵羊(LCT)相关的知识,希望对你有一定的参考价值。

传送门

 

每个点都会跳到另一个点,连边就是一棵树。

 

更改弹力就是换边。

求一个点跳多少次跳到终点就是求这个点的深度,那么只需要维护 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)的主要内容,如果未能解决你的问题,请参考以下文章

AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203

洛谷 3203 HNOI2010 BOUNCE 弹飞绵羊

洛谷 P3203 [HNOI2010]弹飞绵羊 || bzoj2002

洛谷P3203 [HNOI2010]弹飞绵羊LCT

LuoguP3203弹飞绵羊(分块)

BZOJ2002:[HNOI2010]弹飞绵羊——题解