zoukankan      html  css  js  c++  java
  • BZOJ 2049 [Sdoi2008]Cave 洞穴勘测

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2049

    [分析]

      这题仍然也是不需要转化模型的单纯维护森林的问题 [因为两点之间至多一条路径嘛].

      所以仍然是考验LCT的代码与重要函数的实现.

      

      这次主要进行的操作多了Cut(u,v)\Link(u,v)\Query(u,v)

      分别作用是删除边(u,v),连接边(u,v),判断两点是否在同一棵树中[在同一棵树中 <=> 两点间有通路]

      首先说一个新的名叫make_root(x)的辅助性操作,指让x成为x所在树的根

        就是先Access(x),使其与根连通,而且是所在链上深度最大的,然后在所在splay上打下翻转tag,它就成了根

      删除边稍微难想一些:

      

      添边:

        为了满足要求,先将u变成所在树的树根,然后再连上v就好了

      询问:

        直接向上回溯...没什么好说的.

      

      这样说应该有些抽象,具体欢迎看代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=10010;
    
    inline int in(){
        int x=0;char ch=getchar();
        while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    
    char ord[8];
    
    struct Node{
        int l,r,f;
        bool rt,rv;
        
        void trans(){ swap(l,r);}
    }s[maxn];
    
    void push_down(int x){
        if(s[x].rv){
            s[x].trans();
            if(s[x].l) s[s[x].l].rv^=1;
            if(s[x].r) s[s[x].r].rv^=1;
            s[x].rv=0;
        }
    }
    
    void down_tag(int x){
        if(!s[x].rt) down_tag(s[x].f);
        push_down(x);
    }
    
    void zig(int x){
        int y=s[x].f;
        s[x].f=s[y].f;
        if(s[y].rt) s[y].rt=false,s[x].rt=true;
        else{ if(y==s[s[y].f].l) s[s[y].f].l=x;
            else s[s[y].f].r=x;}
        s[y].l=s[x].r;
        if(s[x].r) s[s[x].r].f=y;
        s[x].r=y,s[y].f=x;
    }
    
    void zag(int x){
        int y=s[x].f;
        s[x].f=s[y].f;
        if(s[y].rt) s[y].rt=false,s[x].rt=true;
        else{ if(y==s[s[y].f].l) s[s[y].f].l=x;
            else s[s[y].f].r=x;}
        s[y].r=s[x].l;
        if(s[x].l) s[s[x].l].f=y;
        s[x].l=y,s[y].f=x;
    }
    
    void Splay(int x){
        down_tag(x);
        int y;
        while(!s[x].rt){
            y=s[x].f;
            if(s[y].rt){ if(x==s[y].l) zig(x);
                else zag(x);}
            else{
                int z=s[y].f;
                if(y==s[z].l){ if(x==s[y].l) zig(y),zig(x);
                    else zag(x),zig(x);}
                else { if(x==s[y].r) zag(y),zag(x);
                    else zig(x),zag(x);}
            }
        }
    }
    
    void Access(int x){
        for(int last=0;x;x=s[last=x].f){
            Splay(x);
            s[s[x].r].rt=true;
            s[x].r=last;
            s[last].rt=false;
        }
    }
    
    /*
        make_rt(x)操作表示将x作为x所在树的根
        当Access和Splay操作完后,这个点处于平衡树的顶端而且没有右儿子[切断了联系]
        那么将正棵平衡树翻转一下就让x作为正棵树的最左端点了[没有左儿子]
    */
    
    void make_rt(int x){
        Access(x);
        Splay(x);
        s[x].rv^=1;
    }
    
    bool query(int u,int v){
        while(s[u].f) u=s[u].f;
        while(s[v].f) v=s[v].f;
        return u==v;
    }
    
    void Link(int u,int v){
        make_rt(u);
        s[u].f=v;
    }
    
    void Cut(int u,int v){
        make_rt(u);
        Access(v);
        Splay(v);
        s[s[v].l].f=s[v].f;
        s[s[v].l].rt=true;
        s[v].f=s[v].l=0;
    }
    
    int n,m;
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("2049.in","r",stdin);
        freopen("2049.out","w",stdout);
    #endif
    
        int u,v;
    
        n=in(),m=in();
        for(int i=1;i<=n;i++) s[i].rt=true;
        while(m--){
            scanf("%s",ord);u=in(),v=in();
            if(ord[0]=='Q'){
                if(query(u,v)) puts("Yes");
                else puts("No");
            }
            else if(ord[0]=='C')
                Link(u,v);
            else
                Cut(u,v);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    学习笔记008之Task
    问题: ActivityManager: Warning: Activity not started, its current task has been brought to the front
    问题; No label views point to this text field with an android:labelFor="@+id/@+id/editTextNumber1" attribute
    学习笔记001之[Android开发视频教学].01_06_Android当中的常见控件
    学习笔记002之学习资料
    学习笔记001之环境配置
    设计模式之代理模式
    C# Enum转换
    Json数据序列化对象,及对象序列化为Json格式
    groupby以后取每组前n行
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5128647.html
Copyright © 2011-2022 走看看