[SDOI2008]洞穴勘测

lct模板题。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=10005;
int fa[N],ch[N][2];
bool rev[N];
bool ck(int x) {return x==ch[fa[x]][1];}
bool is_rt(int x) {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void rotate(int x) {
    int f=fa[x],ff=fa[f];bool tag=ck(x);
    if(!is_rt(f)) ch[ff][ck(f)]=x;
    ch[f][tag]=ch[x][tag^1];
    fa[ch[f][tag]]=f;
    ch[x][tag^1]=f;
    fa[f]=x;
    fa[x]=ff;
}
void pushdown(int x) {
    if(rev[x]) {
        swap(ch[x][0],ch[x][1]);
        rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
        rev[x]=0;
    }
}
int top,stk[N];
void splay(int x) {
    stk[top=1]=x;
    for(int i=x;!is_rt(i);i=fa[i]) stk[++top]=fa[i];
    for(int i=top;i;i--) pushdown(stk[i]);
    for(int f;!is_rt(x);rotate(x)) {
        if(!is_rt(f=fa[x])) rotate((ck(x)==ck(f))?f:x);
    }
}
void access(int x) {
    for(int t=0;x;t=x,x=fa[x]) 
        splay(x),ch[x][1]=t;
}
void makeroot(int x) {
    access(x);splay(x);swap(ch[x][0],ch[x][1]);rev[ch[x][1]]^=1,rev[ch[x][0]]^=1;
}
int findroot(int x) {
    access(x);splay(x);
    while(ch[x][0]) x=ch[x][0];
    return x;
}
void link(int x,int y) {
    makeroot(x);
    fa[x]=y;
}
void cut(int x,int y) {
    makeroot(x);access(y);splay(y);
    ch[y][0]=fa[x]=0;    
}
int n,m,x,y;
char opt[10];
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) {
        scanf("%s%d%d",opt,&x,&y);
        switch (opt[0]) {
            case 'C': link(x,y);break;
            case 'D': cut(x,y);break;
            case 'Q': puts(findroot(x)==findroot(y)?"Yes":"No");
        }
    }
    return 0;
}
洞穴勘测
我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9704313.html