洛谷 P3377 模板左偏树

题目:https://www.luogu.org/problemnew/show/P3377

左偏树的模板题;

加深了我对空 merge 的理解;

结构体的编号就是原序列的位置。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const maxn=1e5+5;
int n,m,rt[maxn],fa[maxn];
bool out[maxn];
struct N{
    int ls,rs,val,dis;
}t[maxn];
int get(int x){while(rt[x])x=rt[x]; return x;}
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(t[x].val>t[y].val||(t[x].val==t[y].val&&x>y))swap(x,y);
    t[x].rs=merge(t[x].rs,y);
    if(t[t[x].ls].dis<t[t[x].rs].dis)swap(t[x].ls,t[x].rs);
    if(t[x].rs)t[x].dis=t[t[x].rs].dis+1;
    else t[x].dis=0;
    rt[t[x].ls]=rt[t[x].rs]=x;
    return x;
}
void del(int x)
{
    out[x]=1;
    rt[t[x].ls]=rt[t[x].rs]=0;
    merge(t[x].ls,t[x].rs);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;i++){scanf("%d",&x); t[i].val=x;}
    for(int i=1,op,x,y,u,v;i<=m;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)
        {
            scanf("%d",&y);
            if(out[x]||out[y])continue;
            u=get(x); v=get(y);
            if(u==v)continue;
            merge(u,v);
        }
        else
        {
            if(out[x]){printf("-1
"); continue;}
            u=get(x); printf("%d
",t[u].val);
            del(u);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/9484279.html