模板 - 左偏树

这个并不是左偏树+并查集。

左偏树+并查集里面,每个节点是主要的元素,要关心的节点当前处在哪棵左偏树的管辖内。
而纯粹的左偏树里面,左偏树本身是主要的元素,只关心左偏树本身的合并。

个堆合并了之后,把其中一个完全加入另一个,空的堆就自己去新建一个位置。

多套一层指针来记录各个工厂对应的树现在到了哪里。也就是编号为x的工厂实际是对应哪一棵左偏树。

缺点是删除的节点留在那里占位置。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,m;
const int MAXN=1000005;
int tot,v[MAXN],l[MAXN],r[MAXN],d[MAXN];
int gc[MAXN];   //gc[i]表示编号为i的工厂所在的左偏树是哪个x

class Leftist_Tree {
    int _Merge(int x,int y) {
        if(!x||!y)
            return x+y;
        if(v[x]<v[y])
            swap(x,y);
        r[x]=_Merge(r[x],y);
        if(d[l[x]]<d[r[x]])
            swap(l[x],r[x]);
        d[x]=d[r[x]]+1;
        return x;
    }
    int Build(int val=-1) {
        tot++;
        l[tot]=r[tot]=d[tot]=0;
        v[tot]=val;
        return tot;
    }
  public:
    void Init(int n) {
        tot=n;//当前树的上界到了哪个
        for(int i=1; i<=n; i++) {
            l[i]=r[i]=d[i]=0;
            v[i]=-1;
        }
        l[0]=r[0]=-1;
        d[0]=0;
        v[0]=-1;
    }

    void Push(int x,int val) {
        int gcx=gc[x];
        int rt=Build(val);
        rt=_Merge(rt,gcx);
        gc[x]=rt;
    }
    int Pop(int x) {
        //把x工厂的左偏树的顶端弹出,没有顶端弹出-1
        int gcx=gc[x];
        if(v[gcx]==-1)
            return -1;
        int res=v[gcx];
        gc[x]=_Merge(l[gcx],r[gcx]);
        return res;
    }
    void Merge(int x,int y) {
        //把编号x与编号y的工厂合并到x工厂
        int gcx=gc[x];
        int gcy=gc[y];
        gc[x]=_Merge(gcx,gcy);
        gc[y]=Build();
    }
} lt;


int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    int n,m;
    scanf("%d%d",&n,&m);
    lt.Init(n);
    for(int i=1; i<=m; i++) {
        int ins;
        scanf("%d",&ins);
        switch(ins) {
            case 1: {
                int x,v;
                scanf("%d%d",&x,&v);
                lt.Push(x,v);
                break;
            }
            case 2: {
                int x,y;
                scanf("%d%d",&x,&y);
                lt.Merge(x,y);
                break;
            }
            case 3: {
                int x;
                scanf("%d",&x);
                printf("%d\n",lt.Pop(x));
                break;
            }
        }
    }
}
posted @ 2019-06-15 17:28  韵意  阅读(135)  评论(0编辑  收藏  举报