黑匣子

5 篇文章 0 订阅
3 篇文章 0 订阅

题目大意

给你一些数,你可以选着按顺序插入,和查找第k大的数是哪个,每次查找输出低k大的数

思路:

一个大根堆加一个小根堆…
或者是用平衡树或者是权值线段树…
抱歉我是口头ac,啊哈哈哈。
我的方法是离线做的,你把每次操作都给保存下来,先用所有的数去造一棵树,每次插入就变成删除,然后用数组存每次的查找结果,最后反正输出。

程序:

uses
        math;
const
        maxn=1000000;
var
        s,a,b,f,big,c,d:array [0..maxn] of longint;
        i,j,n,m,hjy:longint;
procedure qsort(l,r:longint);
var
        i,j,mid:longint;
begin
        i:=l; j:=r;
        mid:=a[(l+r) div 2];
        while i<j do
        begin
                while a[i]<mid do inc(i);
                while a[j]>mid do dec(j);
                if i<=j then
                        begin
                          a[0]:=a[i];
                          a[i]:=a[j];
                          a[j]:=a[0];
                          inc(i); dec(j);
                        end;
        end;
        if l<j then qsort(l,j);
        if i<r then qsort(i,r);
end;

procedure make(l,r,o:longint);
var
        i,j,mid:longint;
begin
        if l=r then
                begin
                  f[o]:=a[l];
                  s[o]:=1;
                  big[o]:=a[l];
                  exit;
                end;
        mid:=(l+r) div 2;
        make(l,mid,o*2);
        make(mid+1,r,o*2+1);
        s[o]:=s[o*2]+s[o*2+1];
        big[o]:=max(big[o*2],big[o*2+1]);
end;

procedure find(l,r,x,o,t:longint);
var
        i,j,mid:longint;
begin
        if l=r then
               begin
                 inc(hjy);
                 d[hjy]:=f[o];
                 exit;
               end;
        mid:=(l+r) div 2;
        if s[o*2]+t>=x then find(l,mid,x,o*2,t)
                       else find(mid+1,r,x,o*2+1,t+s[o*2]);
end;


procedure delete(l,r,x,o:longint);
var
        i,j,mid:longint;
begin
        if l=r then
               begin
                 f[o]:=0;
                 s[o]:=0;
                 big[o]:=-maxlongint;
                 exit;
               end;
        mid:=(l+r) div 2;
        if big[o*2]>=x then delete(l,mid,x,o*2)
                       else delete(mid+1,r,x,o*2+1);
        s[o]:=s[o*2]+s[o*2+1];
        big[o]:=max(big[o*2],big[o*2+1]);
end;

begin
        readln(n,m);
        for i:=1 to n do
         read(a[i]);
        c:=a;
        readln;
        for i:=1 to m do
         read(b[i]);
        for i:=0 to maxn do
         big[i]:=-maxlongint;
        qsort(1,n);
        make(1,n,1);
        j:=m;

        for i:=n downto 1 do
        begin
          while b[j]=i do
          begin
            find(1,n,j,1,0);
            dec(j);
          end;
          delete(1,n,c[i],1);
        end;
        for i:=hjy downto 1 do
         writeln(d[i]);
end.
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值