# _bzoj2049 [Sdoi2008]Cave 洞穴勘测【LCT】

①，rotate时，没有判断y是否为根，这点与普通的Splay有点差别。

②，循环变量是i，而不是x！

#include <cstdio>
#include <algorithm>

const int maxn = 10005;

int n, m, t1, t2;
int ch[maxn][2], fa[maxn], stk[maxn], top;
char opr[10], rev[maxn];

inline bool isroot(int x) {
return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}
inline void pushdown(int x) {
if (rev[x]) {
rev[x] = 0;
rev[ch[x][0]] ^= 1;
rev[ch[x][1]] ^= 1;
std::swap(ch[x][0], ch[x][1]);
}
}
inline void rotate(int x) {
int y = fa[x];
if (!isroot(y)) {
if (y == ch[fa[y]][0]) {
ch[fa[y]][0] = x;
}
else {
ch[fa[y]][1] = x;
}
}
fa[x] = fa[y];
int dir = x == ch[y][1];
ch[y][dir] = ch[x][dir ^ 1];
fa[ch[x][dir ^ 1]] = y;
ch[x][dir ^ 1] = y;
fa[y] = x;
}
inline void splay(int x) {
int p;
char flag1, flag2;
top = 0;
stk[top++] = x;
for (int i = x; !isroot(i); i = fa[i]) {
stk[top++] = fa[i];
}
for (int i = top - 1; ~i; --i) {
pushdown(stk[i]);
}
while (!isroot(x)) {
p = fa[x];
if (isroot(p)) {
rotate(x);
}
else {
flag1 = p == ch[fa[p]][1];
flag2 = x == ch[p][1];
if (flag1 ^ flag2) {
rotate(x);
}
else {
rotate(p);
}
rotate(x);
}
}
}
inline void acc(int x) {
int y = 0;
while (x) {
splay(x);
ch[x][1] = y;
y = x;
x = fa[x];
}
}
inline void make_root(int x) {
acc(x);
splay(x);
rev[x] ^= 1;
}
inline void link(int x, int y) {
make_root(x);
fa[x] = y;
}
inline void cutt(int x, int y) {
make_root(x);
acc(y);
splay(y);
ch[y][0] = fa[x] = 0;
}
inline int fnd_root(int x) {
acc(x);
splay(x);
int i;
for (i = x; ch[i][0]; i = ch[i][0]);
return i;
}

int main(void) {
//freopen("in.txt", "r", stdin);
scanf("%d%d", &n, &m);
while (m--) {
scanf("%s%d%d", opr, &t1, &t2);
if (opr[0] == 'Q') {
make_root(t1);
puts(fnd_root(t2) == t1? "Yes": "No");
}
else if (opr[0] == 'C') {