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
", 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
", lca);
        }
        else if(s[1] == 'u') {
            u = read();
            access(u); splay(u);
            ls(u) = fa[ls(u)] = 0;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/reverymoon/p/10091974.html