题解 洛谷P2147/BZOJ2049【[SDOI2008]洞穴勘测】

没有要求维护点权,只需要维护点的连通性即可。

就是朴素的LCT,居然还不要pushup。

感觉有些不适应啊.......不得不说LCT是个神器。

简单分析一下。

  • 对于每种命令:
    • 如果是Connect x y (链接 x y):直接 link(x,y)即可。

    • 如果是Destroy x y (切断 x y):直接 cut(x,y)即可。

    • 如果是Query x y (询问 x y 的连通性):判断findroot(x)findroot(y)是否一致,一致输出Yes,否则输出No

然后就A了.......

Code:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define RI register int
#define A printf("A")
#define C printf(" ") 
using namespace std;
const int N=2e5+2;
template <typename Tp> inline void IN(Tp &x){
    int f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9')if(ch=='-')f=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();x*=f;
}int n,m,f[N],r[N],hep[N],ch[N][2];
inline int chk(int x){return ch[f[x]][1]==x;}
inline int get(int x){return ch[f[x]][0]==x||ch[f[x]][1]==x;}
inline void filp(int x){swap(ch[x][0],ch[x][1]);r[x]^=1;} 
inline void pushdown(int x){
    if(!r[x])return;r[x]=0;
    if(ch[x][0])filp(ch[x][0]);
    if(ch[x][1])filp(ch[x][1]);
}
inline void rotate(int x){
    int y=f[x],z=f[y],k=chk(x),&v=ch[x][!k];
    if(get(y))ch[z][chk(y)]=x;v=y,ch[y][k]=v;
    if(v)f[v]=y;f[y]=x,f[x]=z;return;
}
inline void Splay(int x){
    int y=x,top=0;hep[++top]=y;
    while(get(y))hep[++top]=y=f[y];
    while(top)pushdown(hep[top--]);
    while(get(x)){
        y=f[x],top=f[y];
        if(get(y))rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y);
        rotate(x);
    }return;
} 
inline void Access(int x){
    for(register int y=0;x;x=f[y=x])
       Splay(x),ch[x][1]=y;
}
inline void makeroot(int x){
    Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
    Access(x);Splay(x);
    while(ch[x][0])pushdown(x),x=ch[x][0];
    return x;
}
inline void split(int x,int y){
    makeroot(x);Access(y);Splay(y);
} 
inline void link(int x,int y){
    makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
    makeroot(x);
    if(findroot(y)==x&&f[x]==y&&!ch[x][1]){
        f[x]=ch[y][0]=0;
    }return;
}char op[10];
int main(){
    scanf("%d%d",&n,&m);
    for(register int x,y,i=1;i<=m;++i){
        scanf("%s%d%d",op,&x,&y);
        if(op[0]=='C')link(x,y);
        else if(op[0]=='D')cut(x,y);
        else if(op[0]=='Q'){
            if(findroot(x)==findroot(y))printf("Yes\n");
            else printf("No\n");
        }   
    }return 0;
}
posted @ 2019-01-15 19:38  babingbaboom  阅读(...)  评论(... 编辑 收藏