nyoj 1073
描述输入N个数,M次查询。
每次查询给出一个数x。
要求:每次查询输出前x个数中第i小的数。(i为第i次查询)
你可以假设M <= N,Xi <= Xi+1 <= Xi+2 <= ……. <= Xm (Xm <= N).
-
输入
-
Line0:T
Line1: N,M
Line2…LineN+1:num1,......,numN
LineN+2…LineN+2+M:x1,……,xM
N < 30000, num < 2000000000
输出
-
每次查询输出前i小的数,单独一行。
详细格式请参考样例。
样例输入
-
1 7 4 3 1 -4 2 8 -1000 2 1 2 6 6
样例输出
-
3 3 1 2
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct cmp{
bool operator ()(int x,int y){
return x>y;
}
};
int main(){
int T;
cin>>T;
while(T--){
int n,m;
cin>>n>>m;
int a[n+1];
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
priority_queue<int> big; //大顶堆,top为第i小的数
priority_queue<int,vector<int>,cmp > small; //小顶堆 ,比第i个数大的数
int num;
int count=1;
int t;
for (int i=1;i<=m;i++){
scanf("%d",&num);
while(count<=num){ //当前两个堆的总数小与num个数
if (big.size()<i){ //大顶堆数目不够i,压入数,
//如果新数比小顶堆top小,压入新数,否则压入小顶堆的堆顶,然后将新数压入小顶堆
//维护大顶堆所有数比小顶堆小的特点
if (small.size()==0) {
big.push(a[count]);
count++;
continue;
}
if (a[count]>small.top()){
t=small.top();
small.pop();
small.push(a[count]);
big.push(t);
}
else big.push(a[count]);
}
else {
if (a[count]<big.top()){
t=big.top();
big.pop();
big.push(a[count]);
small.push(t);
}
else small.push(a[count]);
}
count++;
}
if (big.size()<i){ //如果big堆不够i个,将小顶堆堆顶拿过来
t=small.top();
small.pop();
big.push(t);
}
cout<<big.top()<<endl;
}
}
}