[BZOJ2049][[Sdoi2008]Cave 洞穴勘测][LCT]
思路:
题目大意就不放了,貌似是一道LCT裸题。。。三个操作分别是
link
,
cut
和
find
。
感谢这篇集训队论文:https://wenku.baidu.com/view/75906f160b4e767f5acfcedb
以及黄学长的代码:http://hzwer.com/3921.html
感觉LCT的复杂度全靠
splay
和
access
的两个均摊啊。。。
以及由于
splay
的维护是按深度为序,所以把一个点提到根后它的父亲肯定是在它的左儿子中,所以只要一直向左找儿子就好了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Maxn =
10005;
namespace IO {
inline char get(
void) {
static char buf[
1000000], *p1 = buf, *p2 = buf;
if (p1 == p2) {
p2 = (p1 = buf) + fread(buf,
1,
1000000, stdin);
if (p1 == p2)
return EOF;
}
return *p1++;
}
inline void read(
int &x) {
x =
0;
static char c;
bool f =
0;
for (; !(c >=
'0' && c <=
'9'); c = get())
if (c ==
'-') f =
1;
for (; c >=
'0' && c <=
'9'; x = x *
10 + c -
'0', c = get());
if (f) x = -x;
}
inline void read(
char &x) {
x = get();
while(!(x>=
'A' && x <=
'Z')) x = get();
}
inline void write(
int x) {
if (!x)
return (
void)
puts(
"0");
if (x <
0)
putchar(
'-'), x = -x;
static short s[
12], t;
while (x) s[++t] = x %
10, x /=
10;
while (t)
putchar(
'0' + s[t--]);
putchar(
'\n');
}
};
int fa[Maxn], c[Maxn][
2], st[Maxn], top;
bool rev[Maxn];
inline bool isRt(
int x) {
return c[fa[x]][
0] != x && c[fa[x]][
1] != x;
}
inline void pushDown(
int x) {
static int l, r;
l = c[x][
0], r = c[x][
1];
if (rev[x]) {
rev[l] ^=
1; rev[r] ^=
1;
swap(c[x][
0], c[x][
1]);
rev[x] ^=
1;
}
}
inline void rotate(
int x) {
int y = fa[x], z = fa[y], l, r;
r = c[y][
0] == x; l = r ^
1;
if (!isRt(y)) c[z][c[z][
1] == y] = x;
fa[x] = z; fa[y] = x; fa[c[x][r]] = y;
c[y][l] = c[x][r]; c[x][r] = y;
}
inline void splay(
int x) {
st[top =
1] = x;
for (
int i = x; !isRt(i); i = fa[i]) st[++top] = fa[i];
while (top) pushDown(st[top--]);
int y, z;
while (!isRt(x)) {
y = fa[x], z = fa[y];
if (!isRt(y)) c[y][
0] == x ^ c[z][
0] == y ? rotate(x) : rotate(y);
rotate(x);
}
}
inline void access(
int x) {
int t =
0;
while (x) {
splay(x);
c[x][
1] = t;
t = x; x = fa[x];
}
}
inline void rever(
int x) {
access(x); splay(x); rev[x] ^=
1;
}
inline void link(
int x,
int y) {
rever(x); fa[x] = y; splay(x);
}
inline void cut(
int x,
int y) {
rever(x); access(y); splay(y); c[y][
0] = fa[x] =
0;
}
inline int find(
int x) {
access(x); splay(x);
int y = x;
while (c[y][
0]) y = c[y][
0];
return y;
}
int n, m;
int main(
void) {
IO::read(n), IO::read(m);
char op;
int x, y;
while (m--) {
IO::read(op), IO::read(x), IO::read(y);
if (op ==
'C') link(x, y);
else if (op ==
'D') cut(x, y);
else puts(find(x) == find(y) ?
"Yes" :
"No");
}
return 0;
}
完。
By g1n0st
转载请注明原文地址: https://ju.6miu.com/read-12222.html