• P3377 【模板】左偏树(可并堆)


    可以合并的堆。。。板子题

    以dis记录节点能向右走的最大距离

    此结构维护左子树所有dis大于等于右子树的dis。。

    题目:

    如题,一开始有N个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:

    操作1: 1 x y 将第x个数和第y个数所在的小根堆合并(若第x或第y个数已经被删除或第x和第y个数在用一个堆内,则无视此操作)

    操作2: 2 x 输出第x个数所在的堆最小数,并将其删除(若第x个数已经被删除,则输出-1并无视删除操作)

    so  代码。。。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cctype>
    using namespace std;
    #define love_nmr 0
    #define olinr return
    #define nmr 150505
    int son[nmr][2];
    int fa[nmr];
    int dis[nmr];
    int val[nmr];
    int n,m;
    inline int read()
    {
        int f=1,x=0;
        char ch=getchar();
        while(!isdigit(ch))
        {
            if(ch=='-')
                f=-f;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        olinr x*f;
    }
    inline void put(int x)
    {
        if(x<0)
        {
            x=-x;
            putchar('-');
        }
        if(x>9)
            put(x/10);
        putchar(x%10+'0');
    }
    inline int findset(int x)
    {
        while(fa[x]) x=fa[x];
        olinr x;
    }
    inline void swap(int &a,int &b)
    {
        int temp=a; a=b; b=temp;
    }
    inline int merge(int x,int y)
    {
        if(!x||!y) return x+y;
        if(val[x]>val[y]||(val[x]==val[y]&&x>y))
            swap(x,y);
        son[x][1]=merge(son[x][1],y);
        fa[son[x][1]]=x;
        if(dis[son[x][0]]<dis[son[x][1]])
            swap(son[x][0],son[x][1]);
        dis[x]=dis[son[x][1]]+1;
        olinr x;
    }
    inline void pop(int x)
    {
        val[x]=-1;
        fa[son[x][0]]=fa[son[x][1]]=0;
        merge(son[x][0],son[x][1]);
    }
    int main()
    {
        n=read();
        m=read();
        for(int i=1;i<=n;i++)
            val[i]=read();
        int flag,x,y;
        while(m--)
        {
            flag=read();
            if(flag==1)
            {
                x=read();
                y=read();
                if(val[x]==-1||val[y]==-1||x==y)
                    continue;
                int xx=findset(x);
                int yy=findset(y);
                merge(xx,yy);
            }
            else
            {
                x=read();
                if(val[x]==-1)
                {
                    cout<<-1<<endl;
                    continue;
                }
                y=findset(x);
                cout<<val[y]<<endl;
                pop(y);
            }
        }
        olinr love_nmr;
    }   
  • 相关阅读:
    JS: 子项可以来回交换的两个下拉列表
    DOM事件
    DOM基础2——元素
    DOM基础1
    JS: 随机点名程序与万年历
    G_S男女匹配算法(算法的第一个程序2016.09.19)
    Java IO流详尽解析(大神之作)
    细讲解JAVA中的IO流
    c++运算符的优先级(收好不谢)
    java程序——输出当月日历表
  • 原文地址:https://www.cnblogs.com/olinr/p/9448500.html
Copyright © 2020-2023  润新知