# bzoj2049 [Sdoi2008]Cave 洞穴勘测

## 2049: [Sdoi2008]Cave 洞穴勘测

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 10405  Solved: 5070
[Submit][Status][Discuss]

200 5
Query 123 127
Connect 123 127
Query 123 127
Destroy 127 123
Query 123 127

3 5
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3

No
Yes
No

Yes
No

## HINT

100%的数据满足n≤10000, m≤200000 保证所有Destroy指令将摧毁的是一条存在的通道本题输入、输出规模比较大，建议c\c++选手使用scanf和printf进行I\O操作以免超时.

维护五种操作：

1.Reverse(x) :先Access(x),然后Splay(x),最后splay区间翻转.

2.Access(x)：从x往上跳到根，每次都找到t的父亲x,splay(x),x的右儿子设为t.

4.Cut(x,y)：Reverse(x),Access(y),splay(y),将y的左子树切断.

5.Find(x)：Access(x),splay(x),从x开始不断往左子树上跳，直到不能跳为止.

发现我以前的splay模板并不能过，于是换了一个代码比较短的模板，比较容易写错. splay那里要倒着更新.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 200010;
int n,m,son[maxn][20],fa[maxn],rev[maxn],sta[maxn];

void pushdown(int x)
{
if (rev[x])
{
rev[son[x][0]] ^= 1;
rev[son[x][1]] ^= 1;
rev[x] = 0;
swap(son[x][0],son[x][1]);
}
}

bool get(int x)
{
return son[fa[x]][1] == x;
}

bool is_root(int x)
{
return son[fa[x]][0] != x && son[fa[x]][1] != x;
}

void zhuan(int x)
{
int y = fa[x];
int z = fa[y];
int temp = get(x);
if (!is_root(y))
son[z][son[z][1] == y] = x;
fa[x] = z;
son[y][temp] = son[x][temp ^ 1];
fa[son[y][temp]] = y;
son[x][temp ^ 1] = y;
fa[y] = x;
}

void splay(int x)
{
int top = 0;
sta[++top] = x;
int y = x;
for (; !is_root(y); y = fa[y])
sta[++top] = fa[y];
for (int i = top; i >= 1; i--)
pushdown(sta[i]);
int temp;
for (;!is_root(x);zhuan(x))
{
if (!is_root(temp = fa[x]))
{
if (get(temp) == get(x))
zhuan(temp);
else
zhuan(x);
}
}
}

void Access(int x)
{
int t = 0;
for (; x; t = x,x = fa[x])
{
splay(x);
son[x][1] = t;
}
}

void Reverse(int x)
{
Access(x);
splay(x);
rev[x] ^= 1;
}

{
Reverse(x);
fa[x] = y;
splay(x);
}

void Cut(int x,int y)
{
Reverse(x);
Access(y);
splay(y);
son[y][0] = fa[x] = 0;
}

int find(int x)
{
Access(x);
splay(x);
while (son[x][0])
x = son[x][0];
return x;
}

int main()
{
scanf("%d%d",&n,&m);
while (m--)
{
char ch[10];
scanf("%s",ch);
int x,y;
scanf("%d%d",&x,&y);
if (ch[0] == 'Q')
{
if (find(x) == find(y))
puts("Yes");
else
puts("No");
}
if (ch[0] == 'C')
}