[bzoj2049]洞穴勘测

[bzoj2049]洞穴勘测


LCA板子题

注意因为没有确定树的形态,只有先reverse一下把一个节点定为树根再进行操作

  • 代码
#include
using namespace std;
char ch[20];
void getcmd(int& opt,int& x,int& y){
    scanf("%s %d%d",ch+1,&x,&y);
    if(ch[1]=='C')opt=1;
    else if(ch[1]=='D')opt=2;
    else opt=3;
}
const int N=1e4+5;
int null=0;
struct Splay{
    int ch[2],fa;
}t[N];
int rev[N];
int n,m;
inline bool isroot(int x){return t[t[x].fa].ch[1]!=x&&t[t[x].fa].ch[0]!=x;}
inline int son(int x){return t[t[x].fa].ch[1]==x;}

inline void rotate(int x){
    int f=t[x].fa,gf=t[t[x].fa].fa;
    bool a=son(x),b=son(x)^1;
    if(!isroot(f))t[gf].ch[son(f)]=x;
    t[x].fa=gf;
    t[f].ch[a]=t[x].ch[b];t[t[x].ch[b]].fa=f;
    t[x].ch[b]=f;t[f].fa=x;
}

inline void pushdown(int u){
    if(!isroot(u))pushdown(t[u].fa);
    if(rev[u]){
        swap(t[u].ch[0],t[u].ch[1]);
        rev[t[u].ch[0]]^=1;
        rev[t[u].ch[1]]^=1;
        rev[u]=0;
    }
}

inline void splay(int x){
    pushdown(x);
    while(!isroot(x)){
        int f=t[x].fa;
        if(!isroot(f)){
            if(son(x)^son(f))rotate(x);
            else rotate(f);
        }
        rotate(x);
    }
}

inline void access(int x){
    int tmp=0;
    while(x!=null){
        splay(x);
        t[x].ch[1]=tmp;
        tmp=x;x=t[x].fa;
    }
}

void rever(int x){
    access(x),splay(x);
    rev[x]^=1;
}

inline void link(int x,int y){
    rever(x);
    t[x].fa=y;
}

inline void cut(int x,int y){
    rever(x);
    access(y);splay(y);
    t[x].fa=t[y].ch[0]=null;
}

int find(int x){
    access(x);splay(x);
    while(t[x].ch[0])x=t[x].ch[0];
    return x;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int opt,x,y;
        getcmd(opt,x,y);
          if(opt==1) {
            link(x,y);
        } if(opt==2) {
            cut(x,y);
        } if(opt==3) {
            if(find(x)==find(y))printf("Yes\n");
            else printf("No\n");
        }
    }
}

 

你可能感兴趣的:([bzoj2049]洞穴勘测)