bzoj2002: [Hnoi2010]Bounce 弹飞绵羊

lct入门题?只需要Link Cut,不需要换根和维护其他标记

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 200000 + 10;
 6 
 7 int ch[N][2], p[N], sz[N], tl[N];
 8 
 9 int n, m;
10 
11 bool isroot(int x) {
12     return ch[p[x]][0] != x && ch[p[x]][1] != x;
13 }
14 #define l ch[x][0]
15 #define r ch[x][1]
16 void update(int x) {
17     assert(x != 0);    
18     sz[x] = sz[l] + sz[r] + 1;
19 }
20 #undef l
21 #undef r
22 
23 void rotate(int x) {
24     int y = p[x], z = p[y];
25     int l = ch[y][1] == x, r = l ^ 1;
26     if(!isroot(y)) ch[z][ch[z][1] == y] = x;
27     p[ch[x][r]] = y;
28     p[y] = x;
29     p[x] = z;
30 
31     ch[y][l] = ch[x][r];
32     ch[x][r] = y;
33 
34     update(y), update(x);
35 }
36 
37 void splay(int x) {
38     while(!isroot(x)) {
39         int y = p[x], z = p[y];
40         if(!isroot(y)) {
41             if((ch[y][1] == x) ^ (ch[z][1] == y)) rotate(x);
42             else rotate(y);
43         }
44         rotate(x);
45     }
46 }
47 
48 void access(int x) {
49     for(int t = 0; x ; t = x, x = p[x]) {
50         splay(x), ch[x][1] = t, update(x);
51     }
52 }
53 
54 int getroot(int x) {
55     for(access(x), splay(x); ch[x][0]; x = ch[x][0]);
56     return splay(x), x;
57 }
58 
59 void Cut(int x) {
60     access(x), splay(x);
61     p[ch[x][0]] = 0, ch[x][0] = 0;
62     update(x);
63 }
64 
65 void Link(int x, int y) {
66     Cut(x), p[x] = y;
67 }
68 
69 int main() {
70 #ifdef DEBUG
71     freopen("in.txt", "r", stdin);
72 #endif
73 
74     int n; scanf("%d", &n);
75     for(int i = 1; i <= n; i++) {
76         sz[i] = 1, scanf("%d", tl + i);
77         p[i] = min(tl[i] + i, n + 1);
78         tl[i] = p[i];
79     }
80     sz[n + 1] = 1;
81 
82     int m; scanf("%d", &m);
83     while(m--) {
84         int cmd, a, b;
85         scanf("%d%d", &cmd, &a), ++a;
86         if(cmd == 1) {
87             access(a), splay(a);
88             printf("%d\n", sz[a] - 1);
89         } else {
90             scanf("%d", &b);
91             int y = min(a + b, n + 1);
92             if(y != tl[a]) Link(a, tl[a] = y);
93         }
94     }
95 
96     return 0;
97 }
LCT

 

分块也是可以的

每个点下一个维护跳出块的点是哪个,以及要用多少步。

sz取$\sqrt{2n}$比较合适。

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 200000 + 10;
 6 
 7 int next[N], step[N], belong[N], fa[N];
 8 
 9 void modify(int x, int y) {
10     if(belong[x] != belong[y]) {
11         step[x] = 1, next[x] = y;
12     } else {
13         step[x] = step[y] + 1;
14         next[x] = next[y];
15     }
16 }
17 
18 int main() {
19 #ifdef DEBUG
20     freopen("in.txt", "r", stdin);
21 #endif
22 
23     int n; scanf("%d", &n);
24     int bs = sqrt(n * 2) + 1;
25     for(int i = 0; i < n; i++) {
26         belong[i] = i / bs;
27         scanf("%d", fa + i);
28         fa[i] = min(fa[i] + i, n);
29     }
30     belong[n] = -1;
31     for(int i = n-1; i >= 0; i--) modify(i, min(n, fa[i]));
32 
33     int m; scanf("%d", &m);
34     while(m--) {
35         int opt, x;
36         scanf("%d%d", &opt, &x);
37         if(opt == 1) {
38             int ans = 0;
39             while(x != n) {
40                 ans += step[x];
41                 x = next[x];
42             }
43             printf("%d\n", ans);
44         } else {
45             scanf("%d", fa + x);
46             fa[x] = min(fa[x] + x, n);
47             for(int i = x; i >= 0 && belong[i] == belong[x]; i--) {
48                 modify(i, fa[i]);
49             }
50         }
51     }
52 
53     return 0;
54 }
sqrt

 

splay维护括号序列也是可以的。

第一次写splay维护括号序列,用了好多以前没用过的splay写法。

定位指针自底向上的splay知不知道根是谁简直无所谓,随便splay一个就成根了。

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 const int N = 200000 + 10;
  6 
  7 vector<int> G[N];
  8 int dfn[2][N], dfs_clock;
  9 
 10 const int maxnode = 400000 + 10;
 11 int ch[maxnode][2], p[maxnode], val[maxnode], sum[maxnode];
 12 
 13 void dfs(int u) {
 14     val[dfn[0][u] = ++dfs_clock] = 1;
 15     for(unsigned i = 0; i < G[u].size(); i++) {
 16         dfs(G[u][i]);
 17     }
 18     val[dfn[1][u] = ++dfs_clock] = -1;
 19 }
 20 
 21 // splay
 22 
 23 void update(int x) {
 24     sum[x] = val[x];
 25     sum[x] += sum[ch[x][0]];
 26     sum[x] += sum[ch[x][1]];
 27 }
 28 
 29 void rotate(int x) {
 30     int y = p[x], z = p[y];
 31     if(z) ch[z][ch[z][1] == y] = x;
 32     int l = ch[y][1] == x, r = l ^ 1;
 33     p[x] = z, p[y] = x, p[ch[x][r]] = y;
 34     ch[y][l] = ch[x][r], ch[x][r] = y;
 35     update(y), update(x);
 36 }
 37 
 38 void splay(int x, int FA = 0) {
 39     while(p[x] != FA) {
 40         int y = p[x], z = p[y];
 41         if(z) {
 42             if((ch[y][1] == x) ^ (ch[z][1] == y)) rotate(x);
 43             else rotate(y);
 44         }
 45         rotate(x);
 46     }
 47 }
 48 
 49 int tot = 0;
 50 int build(int sz) {
 51     if(sz <= 0) return 0;
 52     int mid = sz >> 1;
 53     int l = build(mid),
 54         x = ++tot,
 55         r = build(sz - mid - 1);
 56     ch[x][0] = l, ch[x][1] = r;
 57     p[l] = x, p[r] = x, update(x);
 58     return x;
 59 }
 60 
 61 int get_pre(int x) {
 62     splay(x), x = ch[x][0];
 63     while(ch[x][1]) x = ch[x][1];
 64     return splay(x), x;
 65 }
 66 
 67 int get_suf(int x) {
 68     splay(x), x = ch[x][1];
 69     while(ch[x][0]) x = ch[x][0];
 70     return splay(x), x;
 71 }
 72 
 73 int split(int x) { //将x作为左边的最后一个元素分裂
 74     splay(x);
 75     int y = ch[x][1];
 76     ch[x][1] = 0, p[y] = 0, update(x);
 77     return y;
 78 }
 79 
 80 bool iot(int x, int y) {
 81     splay(x), splay(y);
 82     if(p[x]) return 1;
 83     return 0;
 84 }
 85 
 86 void merge(int x, int y) { //将x所在的子树与y所在的子树合并
 87     splay(x), splay(y);
 88     while(ch[x][1]) x = ch[x][1];
 89     splay(x), ch[x][1] = y, p[y] = x, update(x);
 90 }
 91 
 92 int main() {
 93 #ifdef DEBUG
 94     freopen("in.txt", "r", stdin);
 95 #endif
 96 
 97     int n; scanf("%d", &n);
 98     for(int i = 1; i <= n; i++) {
 99         int fa; scanf("%d", &fa);
100         fa = min(fa + i, n + 1);
101         G[fa].push_back(i);
102     }
103 
104     dfs(n + 1);
105     
106     {
107         int x = (n + 1) * 2 + 1;
108         ch[x][1] = x + 1, p[ch[x][1]] = x;
109         ch[x+1][0] = build((n + 1) << 1);
110         p[ch[x+1][0]] = x+1;
111         update(x+1), update(x);
112     }
113 
114     int m; scanf("%d", &m);
115     while(m--) {
116         int opt, u, fa;
117         scanf("%d%d", &opt, &u); ++u;
118         if(opt == 1) {
119             int x = get_suf(dfn[0][u]);
120             splay(x);
121             printf("%d\n", sum[ch[x][0]] - 1);
122         } else {
123             scanf("%d", &fa);
124             fa = min(fa + u, n + 1);
125             int l = get_pre(dfn[0][u]);
126             split(l);
127             int r = split(dfn[1][u]);
128             merge(l, r);
129             split(dfn[0][fa]);
130             merge(dfn[0][fa], dfn[1][u]);
131             merge(dfn[1][u], dfn[1][fa]);
132         }
133     }
134 
135     return 0;
136 }
splay

 

posted @ 2015-05-11 23:17  Showson  阅读(223)  评论(0编辑  收藏  举报