zoukankan      html  css  js  c++  java
  • 模板

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

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

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

    多套一层指针来记录各个工厂对应的树现在到了哪里。也就是编号为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
    ",lt.Pop(x));
                    break;
                }
            }
        }
    }
    
  • 相关阅读:
    两个多项式的卷积【NTT】
    Determinant【矩阵的行列式的求法】
    2020 CCPC 长春题解
    Easy Equation【差分+前缀和】
    CF1433G-Reducing Delivery Cost【最短路】
    Interstellar Hunter【2020CCPC秦皇岛-I】
    P4721 【模板】分治 FFT
    关于Spring事务传播行为的个人见解
    InnoDB MVCC实现原理整理
    Nginx学习笔记(五、Nginx缓存与限流)
  • 原文地址:https://www.cnblogs.com/Yinku/p/11028238.html
Copyright © 2011-2022 走看看