poj 1442 Black Box

 /*

题意:向一个容器中不断的添加m个数,然后有n个查询,
每次查询在插入的前u个数中第i个小的数,i初始值是1,每查询一次就自增1
sample: 7 4 3 1 -4 2 8 -1000 2 1 2 6 6
第1次查询:u=1,即插入 3 , 第1 小的数是 3
第2次查询:u=2,即插入 3 1, 第2 小的数是 3
第3次查询:u=6,即插入 3 1 -4 2 8 -1000, 第3 小的数是 1
第3次查询:u=6,即插入 3 1 -4 2 8 -1000, 第4 小的数是 2
所以输出为: 3 3 1 2
思路: 要查询第 i 大的数,需要维护大顶堆和小顶堆,让大顶堆的堆顶小于小顶堆的堆顶
即大顶堆所有元素都小于小顶堆的所有元素.每次插入新元素时,让大顶堆的规模保持为 i-1
则小顶堆的堆顶就是第 i 小的数了

*/

#include <iostream> //大顶堆和小顶堆,查询第i小的数
#include <queue>

using namespace std;
int m,n,arr[30002],res[30002];
int main()
{
priority_queue<int> q1; //大顶堆
priority_queue<int,vector<int>,greater<int> > q2; //小顶堆
cin>>m>>n;

for(int i=1;i<=m;++i)
cin>>arr[i];
int u,cur=0,cnt=0,rear=0;
while(n--)
{
cin>>u;
while(cur<u)
{
int num=arr[++cur]; // cur 指当前处理的arr数组的下标
//以下两种操作都是让大顶堆的规模保持不变
if( !q1.empty() && num<q1.top() ) // 新元素小于大顶堆q1的最大值(堆顶),则需要先弹出q1的堆顶,并把它压入小顶堆,再把新元素压入到大顶堆
{

int t=q1.top();
q1.pop();
q2.push(t);
q1.push(num);
}
else // 新元素比大顶堆q1的最大值(堆顶)还大,则压入小顶堆
{

q2.push(num);
}
}
if(q1.size()<cnt) // cnt 指大顶堆要达到的规模
{

int t=q2.top();
q2.pop();
q1.push(t);
}
res[rear++]=q2.top(); //小顶堆的堆顶就是第cnt+1小的数
cnt++;

}
for(int i=0;i<rear;++i)
cout<<res[i]<<endl;
return 0;
}

posted on 2012-03-14 10:05  sysu_mjc  阅读(139)  评论(0编辑  收藏  举报

导航