zoukankan      html  css  js  c++  java
  • 【模板】左偏树

    题目描述

    题解:

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

    板子:

    #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;
    }
  • 相关阅读:
    .Net 控制台动态刷新使用
    VS 将!=转换成 ≠
    C# 自定义Html分页
    .NET MVC ModelBinder基本使用
    C# 重启电脑 程序自启动
    ASP.NET JsonResult返回日期格式及首字母大写解决
    java快速排序代码实现
    系统高可靠的设计需要考虑哪些方面
    sentinel源码学习--transport模块
    TiDB学习笔记分享--存储篇
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10294893.html
Copyright © 2011-2022 走看看