zoukankan      html  css  js  c++  java
  • [luogu3377]【模板】左偏树(可并堆)

    解题关键:左偏树模板

    1、路径压缩版本

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N=1e5+3;
    int n,m;
    struct tree{
        int l,r;
        int dis,val,fa;
    }tr[N];
    
    int Get(int x){return tr[x].fa==x?x:tr[x].fa=Get(tr[x].fa);}
    
    int Merge(int x,int y){
        if(!x||!y)return x+y;
        if(tr[x].val>tr[y].val||(tr[x].val==tr[y].val&&x>y))
            swap(x,y);
        int &ul=tr[x].l,&ur=tr[x].r;
        ur=Merge(ur,y);
        if(tr[ul].dis<tr[ur].dis)swap(ul,ur);
        tr[ur].fa=tr[ul].fa=x;
        tr[x].dis=tr[ur].dis+1;
        return x;
    }
    
    void Erase(int x){
        int ul=tr[x].l,ur=tr[x].r;
        tr[x].val=-1;tr[ul].fa=ul;tr[ur].fa=ur;
        tr[x].fa=Merge(ul,ur);
    }
    
    int Del(int x){
        int fx=tr[x].fa;
        int ka=Merge(tr[x].l,tr[x].r);
        tr[ka].fa=fx;
        int &ul=tr[fx].l,&ur=tr[fx].r;
        ul==x?ul=ka:ur=ka;
        while(fx){
            if(tr[ul].dis<tr[ur].dis)swap(ul,ur);
            if(tr[fx].dis==tr[ur].dis+1)
                return Get(fx);
            tr[fx].dis=tr[ur].dis+1;
            ka=fx; fx=tr[x].fa;
            ul=tr[fx].l,ur=tr[fx].r;
        }
        return ka;
    }
    
    int Build(){
        queue<int>q;
        for(int i=1;i<=n;i++) q.push(i);
        int x,y,z;
        while(q.size()>1){
            x=q.front();q.pop();
            y=q.front();q.pop();
            z=Merge(x,y);q.push(z);
        }
        return q.front();
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)tr[i].fa=i,scanf("%d",&tr[i].val);
        for(int i=1,c,x,y;i<=m;i++){
            scanf("%d",&c);
            if(c==1){
                scanf("%d%d",&x,&y);
                if(tr[x].val==-1||tr[y].val==-1)continue;
                int nx=Get(x);
                int ny=Get(y);
                if(nx==ny) continue;
                Merge(nx,ny);
            }else{
                scanf("%d",&x);
                if(tr[x].val==-1){
                    puts("-1");
                }else{
                    y=Get(x);
                    printf("%d
    ",tr[y].val);
                    Erase(y);
                }
            }
        }
        return 0;
    }

    2、非路径压缩版本,保留树结构

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int N=1e5+3;
    int n,m;
    struct tree{
        int l,r;
        int dis,val,fa;
    }tr[N];
    
    int Get(int x){
        while(tr[x].fa)x=tr[x].fa;
        return x;
    }
    
    int Merge(int x,int y){
        if(!x||!y)return x+y;
        if(tr[x].val>tr[y].val||(tr[x].val==tr[y].val&&x>y))
            swap(x,y);
        int &ul=tr[x].l,&ur=tr[x].r;
        ur=Merge(ur,y);
        tr[ur].fa=x;
        if(tr[ul].dis<tr[ur].dis)swap(ul,ur);
        tr[x].dis=tr[ur].dis+1;
        return x;
    }
    
    void Erase(int x){
        int ul=tr[x].l,ur=tr[x].r;
        tr[x].val=-1;tr[ul].fa=0;tr[ur].fa=0;
        Merge(ul,ur);
    }
    
    int Del(int x){
        int fx=tr[x].fa;
        int ka=Merge(tr[x].l,tr[x].r);
        tr[ka].fa=fx;
        int &ul=tr[fx].l,&ur=tr[fx].r;
        ul==x?ul=ka:ur=ka;
        while(fx){
            if(tr[ul].dis<tr[ur].dis)swap(ul,ur);
            if(tr[fx].dis==tr[ur].dis+1)
                return Get(fx);
            tr[fx].dis=tr[ur].dis+1;
            ka=fx; fx=tr[x].fa;
            ul=tr[fx].l,ur=tr[fx].r;
        }
        return ka;
    }
    
    int Build(){
        queue<int>q;
        for(int i=1;i<=n;i++) q.push(i);
        int x,y,z;
        while(q.size()>1){
            x=q.front();q.pop();
            y=q.front();q.pop();
            z=Merge(x,y);q.push(z);
        }
        return q.front();
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&tr[i].val);
        for(int i=1,c,x,y;i<=m;i++){
            scanf("%d",&c);
            if(c==1){
                scanf("%d%d",&x,&y);
                if(tr[x].val==-1||tr[y].val==-1)continue;
                int nx=Get(x);
                int ny=Get(y);
                if(nx==ny) continue;
                Merge(nx,ny);
            }else{
                scanf("%d",&x);
                if(tr[x].val==-1){
                    puts("-1");
                }else{
                    y=Get(x);
                    printf("%d
    ",tr[y].val);
                    Erase(y);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    策略模式-观察者模式-装饰者模式-工厂模式-单例模式
    mac下 tomcat8+jdk1.8+servlet+Spring环境搭建中的问题
    删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
    JAVA锁的膨胀过程和优化
    单例模式
    简单工厂模式(静态工厂)和工厂方法模式和抽象工厂模式
    从基层容器类看万变不离其宗的JAVA继承体系
    响应式布局1
    网页加载速度优化4--图片懒加载
    jquery选择器返回值
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/10393577.html
Copyright © 2011-2022 走看看