zoukankan      html  css  js  c++  java
  • 左偏树复习

    左偏树:一种可并堆

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

    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;
    }

     

  • 相关阅读:
    [LeetCode 1029] Two City Scheduling
    POJ 2342 Anniversary party (树形DP入门)
    Nowcoder 106 C.Professional Manager(统计并查集的个数)
    2018 GDCPC 省赛总结
    CF 977 F. Consecutive Subsequence
    Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
    Poj 2337 Catenyms(有向图DFS求欧拉通路)
    POJ 1236 Network of Schools (强连通分量缩点求度数)
    POJ 1144 Network (求割点)
    POJ 3310 Caterpillar(图的度的判定)
  • 原文地址:https://www.cnblogs.com/terra/p/7161002.html
Copyright © 2011-2022 走看看