luogu P2343 宝石管理系统 暴力,思维,二分

P2343 宝石管理系统

题目描述

GY君购买了一批宝石放进了仓库。有一天GY君心血来潮,想要清点他的宝石,于是把m个宝石都取出来放进了宝石管理系统。每个宝石i都有一个珍贵值vi,他希望你能编写程序查找到从大到小第n珍贵的宝石。但是现在问题来了,他非常不小心的留了一些宝石在仓库里面,有可能要往现有的系统中添加宝石。这些宝石的个数比较少。他表示非常抱歉,但是还是希望你的系统能起作用。

输入输出格式

输入格式:

第一行一个整数m,q,表示已经取出来的宝石个数以及接下来的查询或插入操作个数。

第二行m个整数,表示这m个宝石的珍贵值。

以下q行,每行两个整数c,n,

若c=1(即询问),则输出当前第n珍贵的宝石,

若c=2(即插入),则往系统中插入珍贵值为n的宝石。

输出格式:

对于每个c=1(询问),输出当前第n珍贵的宝石的珍贵值vi。

输入输出样例

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

Pre

好把,这题其实是zyf小盆友叫我去做的,一开始想用数组next模拟链表,结果打了个错误百出的版本交了上去,然后就WA+TLE了然后猛然意识到这题直接模拟链表的时复超高

所以开始想用树状数组来记录,然后就怂了,开始寻找其他方法……

暴力qsort一遍,然后每次加入后再qsort = 60 points  

for一遍尝试找第一比他小的,可以直接插入到它前面 ,然后平移数组= 80 points

Solution

// 注意:感觉这似乎不是正解qwq

于是进入正题

首先既然我们可以直接插入加平移数组,既然可以往左平移,为啥不能往右呢?

所以我们可以在平移时加个优化判断向左平移方便还是向右平移方便

------------ubuntu上的gdb坏了,于是只能用write来debug .... 【欲哭无泪】

好,处理完后啦,还是80 points ?

于是机智的你想到了二分

没错再加上二分找第一比他小的 就AC啦
 
原来这么水。。。
 
最后分析一下时间复杂度,忽略二分时间复杂度添加操作总的大概为$O(q ( log^n_2+ lfloor n/2 floor ))|q leq 10000,n leq 110000$,查询就是$O(q)$
 
 1 program wonder;
 2 var
 3   n,q,i,c,x,left,right,aa,bb:longint;
 4   a:array[-110000..110000] of longint;
 5 
 6 procedure qsort(l,r:longint);  //从大到小qsort
 7 var i,j,m,x:longint;
 8 begin
 9     i:=l;  j:=r;  m:=a[(l+r) div 2];
10     repeat
11     while a[i]>m do inc(i);
12     while a[j]<m do dec(j);
13     if i<=j then begin
14                   x:=a[i];a[i]:=a[j];a[j]:=x;
15                   inc(i);dec(j);
16                 end;
17     until i>j;
18     if i<r then qsort(i,r);
19     if j>l then qsort(l,j);
20 end;
21 
22 procedure add;
23 var
24    ii,jj,m:longint;
25 begin
26    
27   ii:=left;  jj:=right;
28   while ii<jj do
29     begin
30       m:=ii+(jj-ii) div 2;
31       if a[m]>x then ii:=m+1
32         else jj:=m-1;
33     end;                    //二分查找第一个比他小的
34 
35   for ii:=ii to right do    //insert
36    if x>a[ii] then
37     begin
38       bb:=n-ii+1;          //bb为右移数组的花费
39       aa:=n-bb;            //aa为左移数组的花费
40       inc(n);              //n为元素个数                          
41       if bb<aa then begin
42                       inc(right); 
43                       for jj:= right downto ii+1 do a[jj]:=a[jj-1];
44                       a[ii]:=x;
45                     end
46       else  begin
47                dec(left);
48                for jj:= left to ii-2 do a[jj]:=a[jj+1];
49                a[ii-1]:=x;
50              end;
51        break;
52     end;
53 end;
54 
55 begin
56   readln(n,q);
57   for i:= 1 to n do
58     read(a[i]);
59 
60   qsort(1,n);
61 
62   left:=1;  right:=n;
63   for i:= 1 to q do
64   begin
65    readln(c,x);
66     if c=1 then writeln(a[left+x-1])  
67       else add;              
68   end;
69 end.
原文地址:https://www.cnblogs.com/bobble/p/6849927.html