[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\n",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\n",tr[y].val);
                Erase(y);
            }
        }
    }
    return 0;
}

 

posted @ 2019-02-18 00:54  Elpsywk  阅读(141)  评论(0编辑  收藏  举报