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

    题目描述

    如题,一开始有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。

     1 #include<bits/stdc++.h>>
     2 using namespace std;
     3 const int N=100010;
     4 int n,m,val[N],ch[N][2],f[N],d[N],a,x,y;
     5 inline int read(){
     6     int res=0,f=1;
     7     char ch=getchar();
     8     while (ch<'0'||ch>'9'){
     9         if (ch=='-'){
    10             f=-f;
    11         }
    12         ch=getchar();
    13     }
    14     while (isdigit(ch)){
    15         res=res*10+ch-'0';
    16         ch=getchar();
    17     }
    18     return res*f;
    19 }
    20 inline int merge(int x,int y)
    21 {
    22     if (x==0||y==0)
    23     {
    24         return x+y;
    25     }
    26     if (val[x]>val[y]||(val[x]==val[y]&&x>y))
    27     {
    28         swap(x,y);
    29     }
    30     ch[x][1]=merge(ch[x][1],y);
    31     f[ch[x][1]]=x;
    32     if (d[ch[x][0]]<d[ch[x][1]])
    33     {
    34         swap(ch[x][0],ch[x][1]);
    35     }
    36     d[x]=d[ch[x][1]]+1;
    37     return x;
    38 }
    39 
    40 inline int get(int x)
    41 {
    42     while (f[x])
    43     {
    44         x=f[x];
    45     }
    46     return x;
    47 }
    48 
    49 inline void pop(int x)
    50 {
    51     val[x]=-1;
    52     f[ch[x][0]]=f[ch[x][1]]=0;
    53     merge(ch[x][0],ch[x][1]);
    54 }
    55 
    56 int main()
    57 {
    58     n=read();m=read();
    59     d[0]=-1;
    60     for (int i=1; i<=n; i++)
    61     {
    62         val[i]=read();
    63     }
    64     for (int i=1; i<=m; i++)
    65     {
    66         a=read();
    67         if (a==1)
    68         {
    69             x=read();y=read();
    70             if(val[x]==-1||val[y]==-1)
    71             {
    72                 continue;
    73             }
    74             if (x==y)
    75             {
    76                 continue;
    77             }
    78             int f1=get(x),f2=get(y);
    79             merge(f1,f2);
    80         }
    81         else
    82         {
    83             x=read();
    84             if (val[x]==-1)
    85             {
    86                 printf("-1
    ");
    87             }
    88             else
    89             {
    90                 int f1=get(x);
    91                 printf("%d
    ",val[f1]);
    92                 pop(f1);
    93             }
    94         }
    95     }
    96 }
    View Code
  • 相关阅读:
    WinForm 清空界面控件值的小技巧
    MVC 图片上传总是request.files.count() 等于0
    LinqToSQL 左连接右连接内链接
    C# utc datetime 互相转化
    mvc javascript form.submit()
    Java API中文版下载
    jQuery的链式操作
    【转】Eclipse/MyEclipse中使用复制粘贴功能卡的解决办法
    servlet什么时候被实例化?
    Jquery总结 $("h3 a", patch);
  • 原文地址:https://www.cnblogs.com/Accpted/p/11213269.html
Copyright © 2011-2022 走看看