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

     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。

    code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<iostream>
     6 
     7 using namespace std;
     8 
     9 const int N = 200100;
    10 int rs[N],ls[N],fa[N],dis[N],val[N];
    11 
    12 inline char nc() {
    13     static char buf[100000],*p1 = buf,*p2 = buf;
    14     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    15 }
    16 inline int read() {
    17     int x = 0,f = 1;char ch = nc();
    18     for (; ch<'0'||ch>'9'; ch = nc()) if (ch=='-') f = -1;
    19     for (; ch>='0'&&ch<='9'; ch = nc()) x = x * 10 + ch - '0';
    20     return x * f;
    21 }
    22 int merge(int x,int y) {
    23     if (!x||!y) return x + y;
    24     if ((val[x]>val[y])||(val[x]==val[y]&&x>y)) swap(x,y);
    25     rs[x] = merge(rs[x],y);
    26     fa[rs[x]] = x;
    27     if (dis[ls[x]]<dis[rs[x]]) swap(ls[x],rs[x]);
    28     dis[x] = dis[rs[x]] + 1;
    29     return x;
    30 }
    31 inline int getmn(int x) {
    32     while (fa[x]) x = fa[x];
    33     return x;
    34 }
    35 inline void del(int x) {
    36     val[x] = -1;
    37     fa[ls[x]] = fa[rs[x]] = 0;
    38     merge(ls[x],rs[x]);
    39 }
    40 int main() {
    41     int n = read(),m = read();
    42     for (int i=1; i<=n; ++i) val[i] = read();
    43     while (m--) {
    44         int opt = read();
    45         if (opt==1) {
    46             int x = read(),y = read();
    47             if (val[x]==-1||val[y]==-1||x==y) continue;
    48             merge(getmn(x),getmn(y));
    49         }
    50         else {
    51             int x = read();
    52             if (val[x]==-1) {puts("-1");continue;}
    53             int y = getmn(x);
    54             printf("%d
    ",val[y]);
    55             del(y);
    56         }
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    【转】Pandas学习笔记(七)plot画图
    【转】Pandas学习笔记(六)合并 merge
    【转】Pandas学习笔记(五)合并 concat
    【转】Pandas学习笔记(四)处理丢失值
    【转】Pandas学习笔记(三)修改&添加值
    【转】Pandas学习笔记(二)选择数据
    17秋 SDN课程 第二次上机作业
    17秋 SDN课程 第三次上机作业
    17秋 SDN课程 第一次上机作业
    Ubuntu 14.04 安装sublime
  • 原文地址:https://www.cnblogs.com/mjtcn/p/8051882.html
Copyright © 2011-2022 走看看