标签:scan 编号 等于 [] 排序 printf while padding 命令
我们使用黑匣子的一个简单模型。它能存入一个整数序列和一个特别的变量i。在初始时刻,黑匣子为空且i等于0。这个黑匣子有执行一系列的命令。有两类命令:
ADD(X):把元素X放入黑匣子;
GET:把i加1的同时,输出黑匣子内所有整数中第i小的数。牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素。
下面表是一个11个命令的例子:
编号 |
命令 |
I |
黑匣子内容 |
输出 |
1 |
ADD(3) |
0 |
3 |
|
2 |
GET |
1 |
3 |
3 |
3 |
ADD(1) |
1 |
1,3 |
|
4 |
GET |
2 |
1,3 |
3 |
5 |
ADD(-4) |
2 |
-4,1,3 |
|
6 |
ADD(2) |
2 |
-4,1,2,3 |
|
7 |
ADD(8) |
2 |
-4,1,2,3,8 |
|
8 |
ADD(-1000) |
2 |
-1000,-4,1,2,3,8 |
|
9 |
GET |
3 |
-1000,-4,1,2,3,8 |
1 |
10 |
GET |
4 |
-1000,-4,1,2,3,8 |
2 |
11 |
ADD(2) |
4 |
-1000,-4,1,2,2,3,8 |
|
现需要一个有效的算法处理给定的一系列命令。ADD和GET命令总数至多有30000个。定义ADD命令的个数为M个,GET命令的个数为N个。我们用下面两个整数序列描述命令序列:
(1)A(1),A(2),…,A(M):加入黑匣子的元素序列。所有的数均为绝对值不超过2000000的整数。例如在上例中A=(3,1,-4,2,8,-1000,2)。
(2)u(1),u(2)…,u(N):u(i)表示第i个GET命令在第u(i)个ADD命令之后,例如在上例中,u=(1,2,6,6,)。
你可以假定自然数序列u(1),u(2),…,u(N)以非降序排列,N<=M,且对于每一个p(1<=p<=N)有p<=u(p)<=M。
第一行存放M和N的值,第二行存放 A(1),A(2),……,A(M) ,第三行存放u(1),u(2),……,u(N)。
输出黑匣子的处理结果。
7 4 3 1 -4 2 8 -1000 2 1 2 6 6
3 3 1 2
1<=n<=m<=30000
此题的询问次数和要查询的数值是数列中第几大有关,就可以考虑用对维护。
需要两个堆,一个维护前 j(询问数)-1小的数中的最大值(大根堆),一个维护剩下的数中的最小值(小根堆)。
按顺序遍历这个数列,对于当前这个数,如果这个数比第二个堆的堆顶要小,把这个数插入到第一个堆,再把第一个堆的堆顶取出来,放到第二个堆,确保第一个堆只有j-1个数。否则就插入到第二个堆。
对于当前位置的询问,ans为第二个堆的堆顶,然后把第二个堆的堆顶放到第一个堆里去,询问数多了一次,所以前j-1个数的堆也要多一个数。(手打堆)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n,m,q,cnt_s=0,cnt_b=0; 5 int d_s[300006],d_b[300006];//d_s[]为小根堆 d_b[]为大根堆 6 int a[300006],b[300006]; 7 void push_s(int x){ 8 d_s[++cnt_s]=x; 9 int now=cnt_s; 10 int fa=now/2,t; 11 while(fa>0&&d_s[now]<d_s[fa]){ 12 t=d_s[fa];d_s[fa]=d_s[now];d_s[now]=t; 13 now=fa;fa=now/2; 14 } 15 } 16 void push_b(int x){ 17 d_b[++cnt_b]=x; 18 int now=cnt_b; 19 int fa=now/2,t; 20 while(fa>0&&d_b[now]>d_b[fa]){ 21 t=d_b[fa];d_b[fa]=d_b[now];d_b[now]=t; 22 now=fa;fa=now/2; 23 } 24 } 25 void pop_s(){ 26 d_s[1]=d_s[cnt_s];cnt_s--; 27 int now,lc,rc,t; 28 now=1;lc=2;rc=3; 29 while((d_s[now]>d_s[lc]||d_s[now]>d_s[rc])&&lc<=cnt_s){ 30 if(d_s[now]>d_s[lc]||rc>cnt_s){ 31 t=d_s[now];d_s[now]=d_s[lc];d_s[lc]=t; 32 now=lc;lc=now*2;rc=lc+1; 33 } 34 else{ 35 t=d_s[now];d_s[now]=d_s[rc];d_s[rc]=t; 36 now=rc;lc=now*2;rc=lc+1; 37 } 38 } 39 } 40 void pop_b(){ 41 d_b[1]=d_b[cnt_b];cnt_b--; 42 int now,lc,rc,t; 43 now=1;lc=2;rc=3; 44 while((d_b[now]<d_b[lc]||d_b[now]<d_b[rc])&&lc<=cnt_b){ 45 if(d_b[now]<d_b[lc]||rc>cnt_b){ 46 t=d_b[now];d_b[now]=d_b[lc];d_b[lc]=t; 47 now=lc;lc=now*2;rc=lc+1; 48 } 49 else{ 50 t=d_b[now];d_b[now]=d_b[rc];d_b[rc]=t; 51 now=rc;lc=now*2;rc=lc+1; 52 } 53 } 54 } 55 int main(){ 56 scanf("%d%d",&n,&m); 57 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 58 for(int i=1;i<=m;i++)scanf("%d",&b[i]); 59 int j=1; 60 for(int i=1;i<=n;i++){ 61 if(a[i]<d_s[1]){ 62 push_b(a[i]); 63 q=d_b[1]; 64 push_s(q);pop_b(); 65 }else 66 { 67 push_s(a[i]); 68 } 69 while(b[j]==i){ 70 q=d_s[1];printf("%d\n",q); 71 push_b(q); 72 pop_s();j++; 73 } 74 } 75 }
标签:scan 编号 等于 [] 排序 printf while padding 命令
原文地址:http://www.cnblogs.com/ttaro/p/7390273.html