BZOJ2049 SDOI2008 洞穴堪测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huangjingyuan107/article/details/81951795

题意

一棵LCT,支持link,cut操作。在线问两个点的连通性。

题解

LCT初学题。
注意两个地方。
splay树维护的是LCT的信息。莫将splay看成被维护信息的树。
如何link和cut?
link很简单。

void link(int x,int y){
    mroot(x);
    tr[x].f=y;
}

但是本人对cut操作一直有个困惑。
就是LCT中没有这条边怎么办?
需要特判。
详见我的博客:LCT学习之旅
reverse标记记得实时传。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10010
#define M 200010 
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct note{
    int x,y,u,v,op;
}qu[M];
struct lct{
    int f,c[2],rev;
}tr[N];
int i,j,k,l,n,m;
int cnt,gs,tot,a[M*2],b[M*2];
char ch;
int Swap(int &x,int &y){x=x^y;y=x^y;x=x^y;}
void init(){
    int i;
    scanf("%d%d",&n,&m);
    fo(i,1,m){
        ch=getchar();
        while((ch^'C')&&(ch^'D')&&(ch^'Q'))ch=getchar();
        if(ch=='C'){
            ch=getchar();
            while(ch>='a'&&ch<='z')ch=getchar();
            scanf("%d%d",&qu[i].x,&qu[i].y);
            a[++tot]=qu[i].x;a[++tot]=qu[i].y;
            qu[i].op=0;
        }else
        if(ch=='D'){
            ch=getchar();
            while(ch>='a'&&ch<='z')ch=getchar();
            scanf("%d%d",&qu[i].x,&qu[i].y);
            a[++tot]=qu[i].x;a[++tot]=qu[i].y;
            qu[i].op=1;
        }else{
            ch=getchar();
            while(ch>='a'&&ch<='z')ch=getchar();
            scanf("%d%d",&qu[i].x,&qu[i].y);
            a[++tot]=qu[i].x;a[++tot]=qu[i].y;
            qu[i].op=2;
        }
    }
}
void lsh(){
    int i;
    fo(i,1,tot)b[i]=a[i];
    sort(b+1,b+tot+1);
    cnt=unique(b+1,b+tot+1)-b-1;
    fo(i,1,m){
        qu[i].u=lower_bound(b+1,b+cnt+1,qu[i].x)-b;
        qu[i].v=lower_bound(b+1,b+cnt+1,qu[i].y)-b;
    }
}
bool isroot(int x){
    return (tr[tr[x].f].c[0]^x)&&(tr[tr[x].f].c[1]^x);
}
int dir(int x){return tr[tr[x].f].c[1]==x;}
void pushrev(int x){
    if(!x)return;
    Swap(tr[x].c[0],tr[x].c[1]);
    tr[x].rev^=1;
}
void pdw(int x){
    if(tr[x].rev){
        pushrev(tr[x].c[0]);
        pushrev(tr[x].c[1]);
        tr[x].rev=0;
    }
}
void rotate(int x){
    int y=tr[x].f,z=dir(x);
    pdw(y);pdw(x);
    if(!isroot(y))tr[tr[y].f].c[dir(y)]=x;
    tr[y].c[z]=tr[x].c[z^1];
    tr[x].f=tr[y].f;
    tr[y].f=x;
    tr[tr[x].c[z^1]].f=y;tr[x].c[z^1]=y;
}
void splay(int x){
    int i,y,z;
    while(!isroot(x)){
        y=tr[x].f;
        if(!isroot(y)){
            rotate(dir(x)^dir(y)?x:y);
        }
        rotate(x);
    }
}
void access(int x){
    int i,y=0;
    while(x){
        splay(x);
        pdw(x);
        tr[x].c[1]=y;
        y=x;
        x=tr[x].f;
    }
}
void mroot(int x){
    access(x);
    splay(x);
    pushrev(x);
}
int groot(int x){
    int w=x;
    access(x);
    pdw(x);
    splay(x);
    while(tr[w].c[0]){
        w=tr[w].c[0];
    }
    return w;
}
void link(int x,int y){
    mroot(x);
    tr[x].f=y;
}
bool judge(int x,int y){
    if(!tr[x].c[0])return 0;
    x=tr[x].c[0];
    while(tr[x].c[1]){
        x=tr[x].c[1];
    }
    return x==y;
}
void cut(int x,int y){
    mroot(x);
    pdw(x);
    access(y);
    splay(y);
    pdw(x);
    if(judge(y,x)){
        tr[tr[y].c[0]].f=0;
        tr[y].c[0]=0;
    }
}
void Operate(){
    int i;
    fo(i,1,m){
        if(qu[i].op==0){
            link(qu[i].u,qu[i].v);
        }else
        if(qu[i].op==1){
            cut(qu[i].u,qu[i].v);
        }else{
            if(groot(qu[i].u)==groot(qu[i].v))
            printf("Yes\n");
            else printf("No\n");
        }
    }
}
int main(){
    init();
    lsh();
    Operate();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/huangjingyuan107/article/details/81951795