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;
}
喵喵喵?喵喵喵! 喵喵喵......