cychester

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 }
View Code

 

posted on 2018-09-21 10:25  cychester  阅读(108)  评论(0编辑  收藏  举报

导航