bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

时间:2022-03-27 19:45:34

link cut tree入门题

首先说明本人只会写自底向上的数组版(都说了不写指针、不写自顶向下QAQ……)

突然发现link cut tree不难写。。。

说一下各个函数作用:

bool isroot(int x):判断x是否为所在重链(splay)的根

void down(int x):下放各种标记

void rotate(int x):在x所在重链(splay)中将x旋转到fa[x]的位置上

void splay(int x):在x坐在重链(splay)中将x旋转到根

void access(int x):把x到x所在树的根变为一条重链,根为链顶,x为链底

void reverse(int x):把x变为所在树的根(先access再打上reverse标记)

void link(int x,int y)连接x,y两点

void cut(int x,int y)断开x,y两点

int find(int x)找到x所在树的根

 #include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define rre(i,r,l) for(int i=(r);i>=(l);i--)
#define re(i,l,r) for(int i=(l);i<=(r);i++)
#define Clear(a,b) memset(a,b,sizeof(a))
#define inout(x) printf("%d",(x))
#define douin(x) scanf("%lf",&x)
#define strin(x) scanf("%s",(x))
#define LLin(x) scanf("%lld",&x)
#define op operator
#define CSC main
typedef unsigned long long ULL;
typedef const int cint;
typedef long long LL;
using namespace std;
void inin(int &ret)
{
ret=;int f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=;ch=getchar();}
while(ch>=''&&ch<='')ret*=,ret+=ch-'',ch=getchar();
ret=f?-ret:ret;
}
int fa[],ch[][],rev[];
bool isroot(int x){return ch[fa[x]][]!=x&&ch[fa[x]][]!=x;}
void down(int x)
{
if(!rev[x])return ;
swap(ch[x][],ch[x][]);
rev[ch[x][]]^=;
rev[ch[x][]]^=;
rev[x]=;
}
void rotate(int x)
{
int y=fa[x],z=fa[y];
if(!isroot(y))
if(ch[z][]==y)ch[z][]=x;
else ch[z][]=x;else ;
fa[x]=z,fa[y]=x;
int d=ch[y][]==x;
fa[ch[x][d^]]=y;
ch[y][d]=ch[x][d^];
ch[x][d^]=y;
}
int sta[],top;
void splay(int x)
{
top=;sta[++top]=x;
for(int i=x;!isroot(i);i=fa[i])sta[++top]=fa[i];
while(top)down(sta[top--]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
if((ch[y][]==x)^(ch[z][]==y))rotate(x);
else rotate(y);else
rotate(x);
}
}
void access(int x)
{
int temp=;
while(x)
{
splay(x);
ch[x][]=temp;
temp=x,x=fa[x];
}
}
void reverse(int x)
{
access(x);splay(x),rev[x]^=;
}
void link(int x,int y)
{
reverse(x);fa[x]=y,splay(x);
}
void cut(int x,int y)
{
reverse(x);access(y);splay(y);ch[y][]=fa[x]=;
}
int find(int x)
{
access(x),splay(x);
int y=x;
while(ch[y][])y=ch[y][];
return y;
}
int n,m;
int main()
{
char s[];
inin(n),inin(m);
re(i,,m)
{
strin(s);
int x,y;inin(x),inin(y);
if(s[]=='C')link(x,y);
else if(s[]=='D')cut(x,y);
else
{
if(find(x)==find(y))printf("Yes\n");
else printf("No\n");
}
}
return ;
}