bzoj2049 洞穴勘探【LCT模板】

解题思路:

LCT模板题,用Link,Cut,Findroot操作即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<vector>
#include<queue>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=10005;
int n,m;
int top,stk[N];
int tot,son[N][2],fa[N],rev[N];
char s[10];

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

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

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

void Rotate(int x)
{
    int y=fa[x],z=fa[y],t=which(x);
    if(z&&!rt(y))son[z][which(y)]=x;
    fa[y]=x,fa[x]=z;
    son[y][t]=son[x][t^1],son[x][t^1]=y;
    if(son[y][t])fa[son[y][t]]=y;
}

void Splay(int x)
{
    stk[top=1]=x;
    for(int i=x;!rt(i);i=fa[i])stk[++top]=fa[i];
    for(int i=top;i;i--)if(rev[stk[i]])pushdown(stk[i]);
    while(!rt(x))
    {
        if(!rt(fa[x]))
        {
            if(which(x)==which(fa[x]))Rotate(fa[x]);
            else Rotate(x);
        }
        Rotate(x);
    }
}

void Access(int x)
{
    for(int y=0;x;y=x,x=fa[x])
    {
        Splay(x),son[x][1]=y;
        if(y)fa[y]=x;
    }
}

int Findroot(int x)
{
    Access(x),Splay(x);
    if(rev[x])pushdown(x);
    while(son[x][0])
    {
        x=son[x][0];
        if(rev[x])pushdown(x);
    }
    Splay(x);
    return x;
}

void Makeroot(int x)
{
    Access(x),Splay(x);
    rev[x]^=1;
}

void Link(int x,int y)
{
    Makeroot(x);fa[x]=y;
}

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



int main()
{
    //freopen("lx.in","r",stdin);
    //freopen("lx.out","w",stdout);
    int x,y;
    n=getint(),m=getint();
    while(m--)
    {
        scanf("%s",s);
        x=getint(),y=getint();
        if(s[0]=='Q')
            Findroot(x)==Findroot(y)?puts("Yes"):puts("No");
        else if(s[0]=='C')
            Link(x,y);
        else if(s[0]=='D')
            Cut(x,y);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值