[Bzoj2049][Sdoi2008]Cave 洞穴勘测

题目链接

一道思路蛮清晰的题,题目有连边,删边,判断两点是否联通三个操作,因为题目中提到了“任意时刻任意两个洞穴之间至多只有一条路径”这一句话。所以在任意时刻,这些联通块都是树形的。所以不是很像splay森林LCT吗。

所以就是LCT板子了......

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 10010;
 4 typedef long long ll;
 5 int fa[maxn], ch[maxn][2], siz[maxn], val[maxn], lazy[maxn], st[maxn];
 6 inline bool isroot(int x) {
 7     return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
 8 }
 9 inline void pushup(int x) {
10     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
11 }
12 inline void pushdown(int x) {
13     if (lazy[x]) {
14         if (ch[x][0])lazy[ch[x][0]] ^= 1;
15         if (ch[x][1])lazy[ch[x][1]] ^= 1;
16         swap(ch[x][0], ch[x][1]);
17         lazy[x] = 0;
18     }
19 }
20 inline void rotate(int x) {
21     int y = fa[x], z = fa[y];
22     int k = ch[y][1] == x;
23     if (!isroot(y))
24         ch[z][ch[z][1] == y] = x;
25     fa[x] = z; ch[y][k] = ch[x][k ^ 1]; fa[ch[x][k ^ 1]] = y;
26     ch[x][k ^ 1] = y; fa[y] = x;
27     pushup(y); pushup(x);
28 }
29 inline void splay(int x) {
30     int f = x, len = 0;
31     st[++len] = f;
32     while (!isroot(f))st[++len] = f = fa[f];
33     while (len)pushdown(st[len--]);
34     while (!isroot(x)) {
35         int y = fa[x];
36         int z = fa[y];
37         if (!isroot(y))
38             rotate((ch[y][0] == x) ^ (ch[z][0] == y) ? x : y);
39         rotate(x);
40     }
41     pushup(x);
42 }
43 inline void access(int x) {
44     for (int y = 0; x; x = fa[y = x])
45         splay(x), ch[x][1] = y, pushup(x);
46 }
47 inline void makeroot(int x) {
48     access(x); splay(x); lazy[x] ^= 1;
49 }
50 int Findroot(int x) {
51     access(x), splay(x);
52     while (ch[x][0])
53         pushdown(x), x = ch[x][0];
54     splay(x);
55     return x;
56 }
57 inline void split(int x, int y) {
58     makeroot(x); access(y); splay(y);
59 }
60 inline void Link(int x, int y) {
61     makeroot(x); fa[x] = y;
62 }
63 inline void Cut(int x, int y) {
64     split(x, y); fa[x] = ch[y][0] = 0; pushup(y);
65 }
66 char s[15];
67 int main() {
68     int n, m, x, y;
69     scanf("%d%d", &n, &m);
70     for (int i = 1; i <= m; i++) {
71         scanf("%s%d%d", s, &x, &y);
72         if (s[0] == 'C')
73             Link(x, y);
74         else if (s[0] == 'D')
75             Cut(x, y);
76         else {
77             if (Findroot(x) == Findroot(y))printf("Yes\n");
78             else printf("No\n");
79         }
80     }
81 }

 

posted @ 2019-09-19 17:30  祈梦生  阅读(125)  评论(0编辑  收藏  举报