zoukankan      html  css  js  c++  java
  • P3377 【模板】左偏树(可并堆)

    题目描述

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

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

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

    输入输出格式

    输入格式:

    第一行包含两个正整数N、M,分别表示一开始小根堆的个数和接下来操作的个数。

    第二行包含N个正整数,其中第i个正整数表示第i个小根堆初始时包含且仅包含的数。

    接下来M行每行2个或3个正整数,表示一条操作,格式如下:

    操作1 : 1 x y

    操作2 : 2 x

    输出格式:

    输出包含若干行整数,分别依次对应每一个操作2所得的结果。

    输入输出样例

    输入样例#1: 复制
    5 5
    1 5 4 2 3
    1 1 5
    1 2 5
    2 2
    1 4 2
    2 2
    输出样例#1: 复制
    1
    2
    

    说明

    当堆里有多个最小值时,优先删除原序列的靠前的,否则会影响后续操作1导致WA。

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=10,M<=10

    对于70%的数据:N<=1000,M<=1000

    对于100%的数据:N<=100000,M<=100000

    样例说明:

    初始状态下,五个小根堆分别为:{1}、{5}、{4}、{2}、{3}。

    第一次操作,将第1个数所在的小根堆与第5个数所在的小根堆合并,故变为四个小根堆:{1,3}、{5}、{4}、{2}。

    第二次操作,将第2个数所在的小根堆与第5个数所在的小根堆合并,故变为三个小根堆:{1,3,5}、{4}、{2}。

    第三次操作,将第2个数所在的小根堆的最小值输出并删除,故输出1,第一个数被删除,三个小根堆为:{3,5}、{4}、{2}。

    第四次操作,将第4个数所在的小根堆与第2个数所在的小根堆合并,故变为两个小根堆:{2,3,5}、{4}。

    第五次操作,将第2个数所在的小根堆的最小值输出并删除,故输出2,第四个数被删除,两个小根堆为:{3,5}、{4}。

    故输出依次为1、2。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N=1e5+5;
    
    inline int read()
    {
        char c=getchar();int num=0,f=1;
        for(;!isdigit(c);c=getchar())
            f=c=='-'?-1:f;
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num*f;
    }
    
    bool del[N];
    int n,m;
    struct NODE
    {
        int v,id;
        bool operator < (const NODE &a) const
        {
            return v==a.v ? id<a.id : v<a.v;
        }
    }a[N];
    struct Node
    {
        NODE v;
        int son[2],d;
    }node[N];
    
    int fa[N];
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    int merge(int x,int y)
    {
        if(!x||!y)
            return x+y;
        if(node[y].v<node[x].v)
            swap(x,y);
        node[x].son[1]=merge(node[x].son[1],y);
        if(!node[x].son[0]||node[node[x].son[0]].d<node[node[x].son[1]].d)
            swap(node[x].son[0],node[x].son[1]);
        if(!node[x].son[1])
            node[x].d=0;
        else
            node[x].d=node[node[x].son[1]].d+1;
        return x;
    }
    
    int erase(int x)
    {
        return merge(node[x].son[0],node[x].son[1]);
    }
    
    int opt,x,y,new_r;
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;++i)
        {
            a[i].v=read();
            a[i].id=i;
            node[i].v=a[i];
            fa[i]=i;
        }
        while(m--)
        {
            opt=read();
            if(opt==1)
            {
                x=read(),y=read();
                if(del[x]||del[y])
                    continue;
                x=find(x),y=find(y);
                if(x==y)
                    continue;
                new_r=merge(x,y);
                fa[x]=fa[y]=new_r;
            }
            else
            {
                x=read();
                if(del[x])
                {
                    puts("-1");
                    continue;
                }
                x=find(x);
                printf("%d
    ",a[x].v);
                new_r=erase(x);
                fa[x]=fa[new_r]=new_r;
                del[x]=true;
            }
        }
        return 0;
    }
  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/lovewhy/p/9028857.html
Copyright © 2011-2022 走看看