• 洛谷P1801 黑匣子


    题目链接:https://www.luogu.com.cn/problem/P1801

    题目描述

    Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量i。最开始的时候Black Box是空的.而i等于0。这个Black Box要处理一串命令。

    命令只有两种:

    ADD(x):把x元素放进BlackBox;

    GET:i加1,然后输出Blackhox中第i小的数。

    记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素。例如:

    我们来演示一下一个有11个命令的命令串。(如下图所示)

    现在要求找出对于给定的命令串的最好的处理方法。ADD和GET命令分别最多200000个。现在用两个整数数组来表示命令串:

    1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M<=200000。例如上面的例子就是A=(3,1,-4,2,8,-1000,2)。

    2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(l,2,6,6)。输入数据不用判错。

    输入格式

    第一行,两个整数,M,N。

    第二行,M个整数,表示A(l)……A(M)。

    第三行,N个整数,表示u(l)……u(N)。

    输出格式

    输出Black Box根据命令串所得出的输出串,一个数字一行。

    输入输出样例

    输入 #1
    7 4
    3 1 -4 2 8 -1000 2
    1 2 6 6
    
    输出 #1
    3
    3
    1
    2
    

    说明/提示

    对于30%的数据,M≤10000;

    对于50%的数据,M≤100000;

    对于100%的数据,M≤200000。

    从数据范围来看,这道题要求一个nlongn的算法,暴力排序是过不了的,需要用堆来解决问题。

    建立一个大根堆b和一个小根堆a分别存储前i小的数和其他的数,用sj存储add命令,用u存储get命令。

    由堆的性质可得a[1]为a中最小元素,b[1]为b中最大元素。

    对于每一次add操作,如果此数s1比b[1]小,即比b中最大元素小,则将b[1]弹出在将此数s1加入b中,然后将弹出的数加入a中,否则直接将s1加入a中,保证b里存放的一定是BlackBox中前i小的数。

    对于get操作,就将a[1]弹出加入b中并将此数输出,此数就是i自家1后第i小的数。

    代码:

    c:

    #include<stdio.h>
    int a[200001],b[200001],lena=0,lenb=0,sj[200001],u[200001],lenu=1,m,n,q;
    void px(int l,int r){
        int i,j,p,mid;
        i=l;j=r;mid=u[(l+r)/2];
        do{
            while(u[i]<mid)i++;
            while(u[j]>mid)j--;
            if(i<=j){
                p=u[i];u[i]=u[j];u[j]=p;
                i++;j--;
            }
        }while(i<=j);
        if(i<r)px(i,r);
        if(l<j)px(l,j);
        return;
    }
    void puta(int d){
        int now,next;
        a[++lena]=d;
        now=lena;
        while(now>1){
            next=now>>1;
            if(a[now]>=a[next])break;
            q=a[now];a[now]=a[next];a[next]=q;
            now=next;
        }
        return;
    }
    int geta(){
        int now,next,res;
        res=a[1];
        a[1]=a[lena--];
        now=1;
        while((now<<1)<=lena){
            next=now<<1;
            if(next<lena&&a[next+1]<a[next])next++;
            if(a[now]<=a[next])break;
            q=a[now];a[now]=a[next];a[next]=q;
            now=next;
        }
        return res;
    }
    void putb(int d){
        int now,next;
        b[++lenb]=d;
        now=lenb;
        while(now>1){
            next=now>>1;
            if(b[now]<=b[next])break;
            q=b[now];b[now]=b[next];b[next]=q;
            now=next;
        }
        return;
    }
    int getb(){
        int now,next,res;
        res=b[1];
        b[1]=b[lenb--];
        now=1;
        while((now<<1)<=lenb){
            next=now<<1;
            if(next<lenb&&b[next+1]>b[next])next++;
            if(b[now]>=b[next])break;
            q=b[now];b[now]=b[next];b[next]=q;
            now=next;
        }
        return res;
    }
    int main(){
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)scanf("%d",sj+i);
        for(int i=1;i<=n;i++)scanf("%d",u+i);
        px(1,n);
        lenu=1;
        int e;
        for(int i=1;i<=m;i++){
            e=sj[i];
            if(lenb>=1&&sj[i]<b[1]){
                e=getb();
                putb(sj[i]);
            }
            puta(e);
            while(lenu<=n&&u[lenu]==i){
                e=geta();
                putb(e);
                printf("%d
    ",e);
                lenu++;
            }
        }
        return 0;
    }

    pascal:

    var
        a,b,sj,u:array[1..200000]of longint;
        lena,lenb,lenu,m,n,q:longint;
    procedure px (l,r:longint);
    var
        i,j,p,mid:longint;
    begin
        i:=l;j:=r;
        mid:=u[(l+r) div 2];
        while i<=j do begin
            while u[i]<mid do i:=i+1;
            while u[j]>mid do j:=j-1;
            if i<=j then begin
                p:=u[i];u[i]:=u[j];u[j]:=p;
                i:=i+1;j:=j-1;
            end;
        end;
        if i<r then px(i,r);
        if l<j then px(l,j);
        exit();
    end;
    procedure puta(d:longint);
    var
        now,next:longint;
    begin
        lena:=lena+1;
        a[lena]:=d;
        now:=lena;
        while now>1 do begin
            next:=now div 2;
            if a[now]>=a[next] then break;
            q:=a[now];a[now]:=a[next];a[next]:=q;
            now:=next;
        end;
        exit();
    end;
    function geta():longint;
    var
        now,next,res:longint;
    begin
        res:=a[1];
        a[1]:=a[lena];
        lena:=lena-1;
        now:=1;
        while now*2<=lena do begin
            next:=now*2;
            if (next<lena)and(a[next+1]<a[next])then next:=next+1;
            if a[now]<=a[next] then break;
            q:=a[now];a[now]:=a[next];a[next]:=q;
            now:=next;
        end;
        exit(res);
    end;
    procedure putb(d:longint);
    var
        now,next:longint;
    begin
        lenb:=lenb+1;
        b[lenb]:=d;
        now:=lenb;
        while now>1 do begin
            next:=now div 2;
            if b[now]<=b[next] then break;
            q:=b[now];b[now]:=b[next];b[next]:=q;
            now:=next;
        end;
        exit();
    end;
    function getb():longint;
    var 
        now,next,res:longint;
    begin
        res:=b[1];
        b[1]:=b[lenb];
        lenb:=lenb-1;
        now:=1;
        while now*2<=lenb do begin
            next:=now*2;
            if (next<lenb)and(b[next+1]>b[next]) then next:=next+1;
            if b[now]>=b[next] then break;
            q:=b[now];b[now]:=b[next];b[next]:=q;
            now:=next;
        end;
        exit(res);
    end;
    var
        i,j,e:longint;
    begin
        readln(m,n);
        for i:=1 to m do read(sj[i]);
        for i:=1 to n do read(u[i]);
        px(1,n);
        lenu:=1;
        for i:=1 to m do begin
            e:=sj[i];
            if (lenb>=1)and(sj[i]<b[1]) then begin
                e:=getb();
                putb(sj[i]);
            end;
            puta(e);
            while (lenu<=n)and(u[lenu]=i) do begin
                e:=geta();
                putb(e);
                writeln(e);
                lenu:=lenu+1;
            end;
        end;
        exit();
    end.

    c++STL版:

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    int a[200001],b[200001],lena=0,lenb=0,sj[200001],u[200001],lenu=1,m,n,k;
    bool cmp(int k,int s){
        return k>s;
    }
    int main(){
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)scanf("%d",sj+i);
        for(int i=1;i<=n;i++)scanf("%d",u+i);
        sort(u+1,u+n+1);
        lenu=1;
        int e;
        for(int i=1;i<=m;i++){
            e=sj[i];
            if(lenb>=1&&sj[i]<b[1]){
                pop_heap(b+1,b+lenb+1);
                e=b[lenb];
                b[lenb]=sj[i];
                push_heap(b+1,b+lenb+1);
            }
            a[++lena]=e;
            push_heap(a+1,a+lena+1,cmp);
            while(lenu<=n&&u[lenu]==i){
                pop_heap(a+1,a+lena+1,cmp);
                e=a[lena--];
                b[++lenb]=e;
                push_heap(b+1,b+lenb+1);
                printf("%d
    ",e);
                lenu++;
            }
        }
        return 0;
    }

    我可能写的不好,如果有问题,请帮忙指出,谢谢。

  • 相关阅读:
    嵌入式编程中使用 do{...} while(0) 的解释
    ESP32学习笔记(一) 环境搭建与下载
    预告:准备开个坑,集中学习一下esp32模块
    【信号与系统】多项式化简方法
    nginx二级域名代理
    nginx配置ssl证书
    springBoot使用阿里云的证书
    vue-cli3项目开启less支持并引入短链接
    一键安装系列
    centos7增加swap
  • 原文地址:https://www.cnblogs.com/sy666/p/12448068.html
Copyright © 2020-2023  润新知