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;
    }
  • 相关阅读:
    HDU 1221 Rectangle and Circle 考虑很多情况,good题
    HDU 1223 打表 + 大数
    17984 FFF团的怒火
    17978 倒不了的塔 注意题目
    .. HDU
    17972 Golden gun的巧克力
    9718 整数因子分解(必做) 分治法
    51NOD 1201 整数划分
    Amazon Rekognition 人脸识别
    AWS Config
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/10393577.html
Copyright © 2011-2022 走看看