【BZOJ2049】【codevs1839】洞穴探测,LCT练习

传送门1
传送门2
写在前面:省选药柜
思路:超级模版啊!连子树大小都不用记录!加一个函数判断
x,y是否在同一颗LCT里就行了(判根),access一下splay一下然后找最左子树,就可以判断了
注意:无
代码:

#include<bits/stdc++.h>
#define pd(i) (i>='0'&&i<='9')
using namespace std;
int n,m,x,y;
int stacks[50010];
char s[10];
struct tree
{
    int fa,ch[2];
    bool lazy;
}a[400010];
int in()
{
    int t=0;
    char ch=getchar();
    while (!pd(ch)) ch=getchar();
    while (pd(ch)) t=(t<<3)+(t<<1)+ch-'0',ch=getchar();
    return t;
}
bool isroot(int x)
{
    return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
}
void pushdown(int x)
{
    if (!a[x].lazy) return;
    a[a[x].ch[0]].lazy^=1;
    a[a[x].ch[1]].lazy^=1;
    swap(a[x].ch[0],a[x].ch[1]);
    a[x].lazy=0; 
}
void rorate(int x,bool mk)
{
    int y=a[x].fa;
    a[x].fa=a[y].fa;
    if (!isroot(y))
    {
        if (a[a[y].fa].ch[0]==y) a[a[y].fa].ch[0]=x;
        else a[a[y].fa].ch[1]=x;
    }
    a[y].ch[!mk]=a[x].ch[mk];
    a[a[x].ch[mk]].fa=y;
    a[x].ch[mk]=y;
    a[y].fa=x;
}
void splay(int x)
{ 
    int y,cnt=0,k=x;
    stacks[++cnt]=k;
    while (!isroot(k)) k=a[k].fa,stacks[++cnt]=k;
    for (int i=cnt;i;i--) pushdown(stacks[i]);
    while (!isroot(x))
    {
        y=a[x].fa;
        if (isroot(y))
        {
            if (a[y].ch[0]==x) rorate(x,1);
            else rorate(x,0);
        }
        else if (a[a[y].fa].ch[0]==y)
        {
            if (a[y].ch[0]==x) rorate(y,1);
            else rorate(x,0);
            rorate(x,1);
        }
        else
        {
            if (a[y].ch[1]==x) rorate(y,0);
            else rorate(x,1);
            rorate(x,0);
        }
    }
}
void access(int x)
{
    for (int y=0;x;y=x,x=a[x].fa)
        splay(x),
        a[x].ch[1]=y;
}
void link(int x,int y)
{
    access(x);
    splay(x);
    a[x].lazy^=1;
    a[x].fa=y;
    splay(x);
}
void cut(int x,int y)
{
    access(x);
    splay(x);
    a[x].lazy^=1;
    access(y);
    splay(y);
    a[y].ch[0]=a[x].fa=0;
}
int findroot(int x)
{
    access(x);
    splay(x);
    while (a[x].ch[0]) x=a[x].ch[0];
    return x;
}
main()
{
    n=in();m=in();
    while (m--)
    {
        scanf("%s",s);
        x=in();y=in();
        if (s[0]=='Q')
        {
            if (findroot(x)==findroot(y)) printf("Yes\n");
            else printf("No\n");
        }
        else if (s[0]=='C') link(x,y);
        else cut(x,y);
    } 
}

你可能感兴趣的:(【BZOJ2049】【codevs1839】洞穴探测,LCT练习)