【模板】左偏树

题目描述

题解:

左偏树,一棵向左倾斜的二叉树。

板子:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100050;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x =  f*c;
}
int n,m,fa[N],v[N],dis[N],ls[N],rs[N];
int merge(int x,int y)
{
    if(!x||!y)return x+y;
    if(v[x]>v[y]||(v[x]==v[y]&&x>y))swap(x,y);
    rs[x] = merge(rs[x],y);
    fa[rs[x]] = x;
    if(dis[ls[x]]<dis[rs[x]])swap(ls[x],rs[x]);
    dis[x] = dis[rs[x]]+1;
    return x;
}
int get_top(int x)
{
    while(fa[x])x=fa[x];
    return x;
}
int erase(int x)
{
    if(fa[x]==-1)return -1;
    x = get_top(x);
    fa[x] = -1;
    int u = merge(ls[x],rs[x]);
    fa[u] = 0;
    return v[x];
}
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;i++)
    {
        read(v[i]);
        dis[i] = 1;
    }
    for(int opt,x,y,i=1;i<=m;i++)
    {
        read(opt);
        if(opt==1)
        {
            read(x),read(y);
            if(fa[x]==-1||fa[y]==-1)continue;
            int tx = get_top(x),ty = get_top(y);
            if(tx==ty)continue;
            int u = merge(tx,ty);
            fa[u] = 0;
        }else
        {
            read(x);
            printf("%d
",erase(x));
        }
    }
    return 0;
}

 $upd:$

之前版本被$luogu$数据卡掉了,$get_top$操作是$O(n)$的。(0_0)

更新路径压缩的做法。

首先合并两棵树就并一下,删除操作要求删除堆顶元素。

肯定是不能直接删的。

怎么做呢,合并儿子后将自己的指针指向新的堆顶就好了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100050;
template<typename T>
inline void read(T&x)
{
    T f =1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int n,m,ch[N][2],v[N],dep[N],ff[N];
int findrt(int x){return x==ff[x]?x:ff[x]=findrt(ff[x]);}
int merge(int x,int y)
{
    if(!(v[x]*v[y]))return x+y;
    if(v[x]>v[y]||(v[x]==v[y]&&x>y))swap(x,y);
    ch[x][1] = merge(ch[x][1],y);ff[ch[x][1]]=x;
    if(dep[ch[x][0]]<dep[ch[x][1]])swap(ch[x][0],ch[x][1]);
    dep[x]=dep[ch[x][1]]+1;
    return x;
}
bool ot[N];
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;i++)
        read(v[i]),dep[i]=1,ff[i]=i;
    for(int op,x,y,i=1;i<=m;i++)
    {
        read(op),read(x);
        if(op==1)
        {
            read(y);
            if(ot[x]||ot[y])continue;
            x = findrt(x);
            y = findrt(y);
            if(x!=y)
                merge(x,y);
        }else
        {
            if(ot[x])
            {
                puts("-1");
                continue;
            }
            x = findrt(x);
            ot[x] = 1;
            printf("%d
",v[x]);
            int now = merge(ch[x][0],ch[x][1]);
            ff[x] = ff[now] = now;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10294893.html