解题报告 『[SDOI2008]洞穴勘测(LCT)』

原题地址

非常基础的增删边 + 询问,没什么好讲的。

 

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = (a); i <= (b); i++)

const int maxn = 1e4 + 5;

int n, m;
int fa[maxn], rev[maxn], ch[maxn][3];

int get(int x) {return x == ch[fa[x]][1];}

int is_root(int x) {return x ^ ch[fa[x]][0] && x ^ ch[fa[x]][1];}

int read() {
    int x = 0, flag = 0;
    char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') {
        flag = 1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ '0');
        ch = getchar();
    }
    return flag ? -x : x;
}

void push_down(int x) {
    if (rev[x]) {
        ch[x][0] ^= ch[x][1] ^= ch[x][0] ^= ch[x][1];
        rev[ch[x][0]] ^= 1;
        rev[ch[x][1]] ^= 1;
        rev[x] = 0;
    }
}

void update(int x) {
    if (!is_root(x)) update(fa[x]);
    push_down(x);
}

void rotate(int x) {
    int y = fa[x], z = fa[y], chx = get(x), chy = get(y);
    if (!is_root(y)) ch[z][chy] = x;
    ch[y][chx] = ch[x][chx ^ 1];
    fa[ch[x][chx ^ 1]] = y;
    ch[x][chx ^ 1] = y;
    fa[y] = x;
    fa[x] = z;
}

void splay(int x) {
    update(x);
    for (register int f = fa[x]; f = fa[x], !is_root(x); rotate(x))
        if (!is_root(f)) rotate(get(x) == get(f) ? f : x);
}

void access(int x) {
    for (register int p = 0; x; p = x, x = fa[x]) {
        splay(x);
        ch[x][1] = p;
    }
}

int find(int x) {
    access(x);
    splay(x);
    while (ch[x][0]) {
        push_down(x);
        x = ch[x][0];
    }
    return x;
}

void make_root(int x) {
    access(x);
    splay(x);
    rev[x] ^= 1;
    push_down(x);
}

void split(int u, int v) {
    make_root(u);
    access(v);
    splay(v);
}

void link(int u, int v) {
    make_root(u);
    if (u ^ find(v)) fa[u] = v;
    else return;
}

void cut(int u, int v) {
    split(u, v);
    if (ch[v][0] == u && !ch[u][1])
        fa[u] = ch[v][0] = 0;
    else return;
}

int main() {
    n = read(), m = read();
    rep(i, 1, m) {
        int u, v;
        char opt[10];
        scanf("%s", opt), u = read(), v = read();
        if (opt[0] == 'C') link(u, v);
        if (opt[0] == 'D') cut(u, v);
        if (opt[0] == 'Q') {
            make_root(u);
            if (u == find(v)) printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
} 
View Code
posted @ 2019-08-22 15:22  雲裏霧裏沙  阅读(155)  评论(0编辑  收藏  举报