SPOJ8791 DYNALCA LCT


考虑\(LCT\)

不难发现,我们不需要换根...

对于操作\(1\)\(splay(u)\)然后连虚边即可

对于操作\(3\),我们可以先\(access(u)\),然后再\(access(v)\),然后查最后一个虚边变实边的点

对于操作\(2\)

可以选择\(access(u), splay(u)\),然后从\(u\)所在的\(splay\)中删去\(u\)

也可以选择\(access(u), access(v), splay(u)\),这时,边\((u, v)\)成为虚边,十分好删除

复杂度\(O(n \log n)\)


版本1:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
    
#define gc getchar
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

const int sid = 1e5 + 5;

int n, m;
char s[sid];
int son[sid][2], fa[sid], pra[sid];

#define ls(o) son[(o)][0]
#define rs(o) son[(o)][1]

inline bool isrc(int o) { return rs(fa[o]) == o; }
inline bool isr(int o) { return !fa[o] || (ls(fa[o]) != o && rs(fa[o]) != o); }

inline void rotate(int o) {
    int f = fa[o], g = fa[f];
    int ro = isrc(o), rf = isrc(f), p = son[o][ro ^ 1];
    if(!isr(f)) son[g][rf] = o; son[o][ro ^ 1] = f; son[f][ro] = p;
    fa[p] = f; fa[f] = o; fa[o] = g;
}

inline void splay(int o) {
    while(!isr(o)) {
        int f = fa[o];
        if(!isr(f)) rotate(isrc(f) == isrc(o) ? f : o);
        rotate(o);
    }
}

int lca = 0;
inline void access(int o) {
    int lst = 0;
    while(o) {
        splay(o); rs(o) = lst;
        lca = lst = o; o = fa[o];
    }
}

int main() {
    n = read(); m = read();
    rep(i, 1, m) {
        int u, v;
        scanf("%s", s);
        if(s[1] == 'i') {
            u = read(); v = read();
            splay(u); pra[u] = v; fa[u] = v;
        }
        else if(s[1] == 'c') {
            u = read(); v = read();
            access(u); access(v);
            printf("%d\n", lca);
        }
        else if(s[1] == 'u') {
            u = read();
            access(u); access(pra[u]);
            splay(u); fa[u] = 0;
        }
    }
    return 0;
}

版本\(2\)

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
    
#define gc getchar
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

const int sid = 1e5 + 5;

int n, m;
char s[sid];
int son[sid][2], fa[sid], pra[sid];

#define ls(o) son[(o)][0]
#define rs(o) son[(o)][1]

inline bool isrc(int o) { return rs(fa[o]) == o; }
inline bool isr(int o) { return !fa[o] || (ls(fa[o]) != o && rs(fa[o]) != o); }

inline void rotate(int o) {
    int f = fa[o], g = fa[f];
    int ro = isrc(o), rf = isrc(f), p = son[o][ro ^ 1];
    if(!isr(f)) son[g][rf] = o; son[o][ro ^ 1] = f; son[f][ro] = p;
    fa[p] = f; fa[f] = o; fa[o] = g;
}

inline void splay(int o) {
    while(!isr(o)) {
        int f = fa[o];
        if(!isr(f)) rotate(isrc(f) == isrc(o) ? f : o);
        rotate(o);
    }
}

int lca = 0;
inline void access(int o) {
    int lst = 0;
    while(o) {
        splay(o); rs(o) = lst;
        lca = lst = o; o = fa[o];
    }
}

int main() {
    n = read(); m = read();
    rep(i, 1, m) {
        int u, v;
        scanf("%s", s);
        if(s[1] == 'i') {
            u = read(); v = read();
            splay(u); pra[u] = v; fa[u] = v;
        }
        else if(s[1] == 'c') {
            u = read(); v = read();
            access(u); access(v);
            printf("%d\n", lca);
        }
        else if(s[1] == 'u') {
            u = read();
            access(u); splay(u);
            ls(u) = fa[ls(u)] = 0;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/reverymoon/p/10091974.html
LCT