bzoj 2049 [Sdoi2008]Cave 洞穴勘测 LCT

题面

题目传送门

解法

LCT模板题

有些博客讲得挺好的,转一下

博客

这个挺详细的

时间复杂度:\(O(m\ log\ n)\)尽管常数巨大

代码

#include <bits/stdc++.h>
#define N 20010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
    x = 0; int f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
struct Node {
    int fa, rev, pathfa, child[2];
} t[N];
int n, m;
int son(int x, int y) {return t[x].child[1] == y;}
void rev(int x) {t[x].rev ^= 1;}
void Clear() {
    for (int i = 1; i <= n; i++)
        t[i] = (Node) {0, false, 0, 0, 0};
}
void pushdown(int k) {
    int x = t[k].rev;
    if (x) {
        swap(t[k].child[0], t[k].child[1]);
        rev(t[k].child[0]), rev(t[k].child[1]);
        t[k].rev = false; 
    }
}
void Connect(int x, int y, int k) {t[x].child[k] = y, t[y].fa = x;}
void Rotate(int x) {
    int y = t[x].fa, z = t[y].fa; pushdown(y);
    pushdown(x); int d = son(y, x);
    swap(t[x].pathfa, t[y].pathfa);
    Connect(z, x, son(z, y));
    Connect(y, t[x].child[!d], d);
    Connect(x, y, !d);
}
void Splay(int x) {
    while (t[x].fa) {
        int y = t[x].fa, z = t[y].fa;
        if (z) {
            pushdown(z), pushdown(y);
            (son(z, y) ^ son(y, x)) ? Rotate(x) : Rotate(y);
        }
        Rotate(x);
    }
}
void expose(int x) {
    Splay(x); pushdown(x);
    int y = t[x].child[1];
    t[y].fa = 0, t[y].pathfa = x;
    t[x].child[1] = 0;
}
void access(int x) {
    for (expose(x); t[x].pathfa; Splay(x)) {
        expose(t[x].pathfa);
        Connect(t[x].pathfa, x, 1);
        t[x].pathfa = 0;
    }
}
void evert(int x) {access(x), Splay(x), rev(x);}
void link(int x, int y) {evert(y), t[y].pathfa = x;}
void cut(int x, int y) {
    evert(x), access(y);
    Splay(y); pushdown(y);
    t[t[y].child[0]].fa = 0;
    t[y].child[0] = 0;
}
int Find(int x) {
    access(x);
    for (pushdown(x); t[x].child[0]; x = t[x].child[0], pushdown(x));
    return x;
}
int main() {
    read(n), read(m); Clear();
    while (m--) {
        char st[10];
        scanf(" %s", st);
        int x, y; read(x), read(y);
        if (st[0] == 'C') link(x, y);
        if (st[0] == 'D') cut(x, y);
        if (st[0] == 'Q') {
            int tx = Find(x), ty = Find(y);
            if (tx == ty) cout << "Yes\n";
                else cout << "No\n";
        }
    }
    return 0;
}
posted @ 2018-08-14 22:14  谜のNOIP  阅读(...)  评论(... 编辑 收藏