• 左偏树复习


    左偏树:一种可并堆

    外节点:左子树为空或右子树为空

    dist(i)i到其后代中最近的外节点经过的边数

    性质:

    ①节点键值小于等于它左右子节点键值

    ②节点左子节点距离不小于右子节点

    ——>左偏树的左右子树都是左偏树

    ——>③节点距离等于它右子节点距离+1(空节点dist-1

    ——>④若一颗左偏树距离为k,则其至少有2k+1-1个节点(完全二叉树)

    ——>⑤一颗N个节点的左偏树距离最多为floor(log(N+1))-1;

    合并(Merge)(A,B——>C

    ①判断是否交换,使A的根节点<=B的根节点

    ②把A的根节点设为新树的节点

    Merge(right(A),B)

    ④若right(A)距离比left(A)大,交换left(A)right(A),并更新A的距离

    插入(Insert(A,x))

    ①建立单节点x新树B

    Merge(A,B)

    删除最小节点

    ①取出根节点

    ②合并左右子树

    构建

    算法一:逐点插入,nlogn

    算法二

    ①讲n个节点放入先进先出队列

    ②从队首取出两颗左偏树,合并后加入队尾

    ③重复上述操作直至队列中只剩一棵树

    O(n)

    删除任意已知节点(从外部有映射指向)

    ①找到该节点,删除,Merge其左右子树,maintain该节点

    maintain:

    若当前节点为根节点或当前节点dist+1=父节点,操作结束,否则

       1.若树为左子树,若其距离+1<父节点距离,则父节点距离=当前节点距离+1,再调整左右子树,maintain父节点;若其距离+1>父节点距离,跳出

       2.若树为右子树,若其距离<=左子树,父节点距离=当前节点距离+1,maintain父节点;若其距离>左子树,交换左右子树,维护父节点距离,若父节点距离不变,则跳出,否则maintain父节点

    O(logn)

     

    左偏树基本操作

    #include<cstdio>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    
    const int MAXN=200000+5;
    const int NUL=-1;
    
    int tot;
    
    struct node{
        int l,r,fa,dist,key;
    }tr[MAXN];
    
    inline void sw(int &a,int &b) {int t=a;a=b;b=t;return;}
    
    int build(int x)
    {
        ++tot;
        tr[tot].l=tr[tot].r=tr[tot].fa=NUL;
        tr[tot].dist=0;tr[tot].key=x;
        return tot;
    }
    
    int Merge(int a,int b)
    {
        if (a==NUL) return b;
        if (b==NUL) return a;
        int t;
        if (tr[a].key>tr[b].key) sw(a,b);
        tr[a].r=Merge(tr[a].r,b);
        if (tr[tr[a].r].dist>tr[tr[a].l].dist) sw(tr[a].r,tr[a].l);
        tr[a].dist=tr[tr[a].r].dist+1;
        return a;
    }
    
    int Insert(int a,int x)
    {
        x=build(x);
        return Merge(a,x);
    }
    
    inline int pop(int a) {return Merge(tr[a].l,tr[a].r);}
    
    inline int init1(int* s,int l,int r)
    {
        int x=build(s[l]);
        rep(i,l+1,r) x=Insert(x,s[i]);
        return x;
    }
    
    int q[4*MAXN];
    inline int init2(int* s,int l,int r)
    {
        int h,t;
        h=t=0;
        rep(i,l,r) q[++t]=build(s[i]);
        int x,y;
        while (h+1<t)
        {
            x=q[++h];y=q[++h];
            q[++t]=Merge(x,y);
        }
        return q[t];
    }
    
    int main()
    {
        return 0;
    }

    左偏树+并查集(每个并查集的最终返回值为所在左偏树的根)

    #include<cstdio>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    
    const int MAXN=200000+5;
    const int NUL=-1;
    
    int fa[MAXN];
    int tot;
    
    struct node{
        int l,r,dist,key;
    }tr[MAXN];
    
    inline void sw(int &a,int &b) {int t=a;a=b;b=t;return;}
    
    void init()
    {
        tot=0;
    }
    
    int getfather(int x)
    {
        if (fa[x]==x) return x;
            else return fa[x]=getfather(fa[x]);
    }
    
    int build(int x)
    {
        ++tot;
        tr[tot].l=tr[tot].r=NUL;
        tr[tot].dist=0;tr[tot].key=x;
        fa[tot]=tot;
        return tot;
    }
    
    int Merge(int a,int b)
    {
        if (a==NUL) return b;
        if (b==NUL) return a;
        int t;
        if (tr[a].key<tr[b].key) sw(a,b);
        tr[a].r=Merge(tr[a].r,b);
        if (tr[tr[a].r].dist>tr[tr[a].l].dist) sw(tr[a].r,tr[a].l);
        tr[a].dist=tr[tr[a].r].dist+1;
    
        fa[b]=a;
        return a;
    }
    
    int Insert(int a,int x)
    {
        x=build(x);
        return Merge(a,x);
    }
    
    inline int pop(int a)
    {
        int x=Merge(tr[a].l,tr[a].r);fa[x]=x;return x;
    }int main()
    {
        return 0;
    }

    模板题hdu1512

    #include<cstdio>
    using namespace std;
    
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    
    const int MAXN=100000+5;
    const int NUL=-1;
    
    int fa[MAXN];
    int tot;
    
    struct node{
        int l,r,dist,key;
    }tr[MAXN];
    
    inline void sw(int &a,int &b) {int t=a;a=b;b=t;return;}
    
    void init()
    {
        tot=0;
    }
    
    int getfather(int x)
    {
        if (fa[x]==x) return x;
            else return fa[x]=getfather(fa[x]);
    }
    
    int build(int x)
    {
        ++tot;
        tr[tot].l=tr[tot].r=NUL;
        tr[tot].dist=0;tr[tot].key=x;
        fa[tot]=tot;
        return tot;
    }
    
    int Merge(int a,int b)
    {
        if (a==NUL) return b;
        if (b==NUL) return a;
        int t;
        if (tr[a].key<tr[b].key) sw(a,b);
        tr[a].r=Merge(tr[a].r,b);
        if (tr[tr[a].r].dist>tr[tr[a].l].dist) sw(tr[a].r,tr[a].l);
        tr[a].dist=tr[tr[a].r].dist+1;
    
        fa[b]=a;
        return a;
    }
    
    int Insert(int a,int x)
    {
        x=build(x);
        return Merge(a,x);
    }
    
    inline int pop(int a)
    {
        int x=Merge(tr[a].l,tr[a].r);fa[x]=x;
        tr[a].l=tr[a].r=NUL;fa[a]=a;tr[a].dist=0;
        return x;
    }
    
    int id[MAXN],x,n,m,y,temp,s;
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            init();
            rep(i,1,n)
            {
                scanf("%d",&x);
                build(x);
            }
            scanf("%d",&m);
            rep(i,1,m)
            {
                scanf("%d%d",&x,&y);
                //rep(i,1,n) printf("%d ",fa[i]);
                //printf("
    ");
                //rep(i,1,n) printf("%d ",tr[i].r);
                //printf("
    ");
                x=getfather(x);y=getfather(y);
                if (x==y)
                {
                    printf("-1
    ");
                    continue;
                }   else
                {
                    x=Merge(x,y);
                    printf("%d
    ",tr[x].key/2);
                    tr[x].key/=2;
                    Merge(pop(x),x);
                }
            }
        }
        return 0;
    }

     

  • 相关阅读:
    Linux command: grep
    VirtualBox内Linux系统怎样与Windows共享文件夹
    Centos 安装R
    Cannot retrieve metalink for repository: epel 错误解决办法
    sed 替换换行回车
    Get and Set Column/Row Names for Data Frames
    TCGA phenotype各列的含义
    R语言 格式化数字
    qvalue: Check that you have valid p-values or use a different range of lambda
    淘宝开源的H5移动开发UI框架genie-ui
  • 原文地址:https://www.cnblogs.com/terra/p/7161002.html
Copyright © 2020-2023  润新知