左偏树复习

左偏树:一种可并堆

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

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("\n");
            //rep(i,1,n) printf("%d ",tr[i].r);
            //printf("\n");
            x=getfather(x);y=getfather(y);
            if (x==y)
            {
                printf("-1\n");
                continue;
            }   else
            {
                x=Merge(x,y);
                printf("%d\n",tr[x].key/2);
                tr[x].key/=2;
                Merge(pop(x),x);
            }
        }
    }
    return 0;
}

 

 

 

posted on 2017-07-13 15:56  心里只有学习  阅读(165)  评论(0编辑  收藏  举报

导航