题意:给出两种命令:
ADD(x):把 x 元素放进 Black Box;
GET:i 加 1,然后输出 Black Box 中第 i 小的数。
输出每次GET操作的结果。
题解:
注意到每次求的第k小中,k从1开始递增。则维护一个大根堆和一个小根堆,大根堆里记录前K小的数字,小根堆里记录其他的数字。
这样构造有一个性质:
1.大根堆里最大的数即为当前数组中的第K小。
在遇到GET操作之前,对于每个待加入的数字,判断其是否为前K小,若是,则加入到大根堆中,并把大根堆中最大的数放到小根堆中;否则直接加入小根堆。
GET操作:取出小根堆里面最小的数即为答案,再将这个数取出加入到大根堆中,满足上面的性质。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 200005, MAXM = 200005;
int a[MAXN];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k * 10 + ch - '0'; ch = getchar();}
return k * f;
}
priority_queue <int> q1, q2;
//q1为小根堆,q2为大根堆
int main(){
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int m = read(), n = read();
for(int i = 1; i <= m; i++){
a[i] = read();
}
// for(int i = 1; i <= m; i++){
// printf("%d ", -q1.top());
// q1.pop();
// }
int now = 0, kth = 0, cur = 0;
for(int i = 1; i <= n; i++){
int k = read();
while(now < k){
now++;
if(!q2.empty()){
int x = q2.top();
if(x > a[now]){
q2.pop();
q1.push(-x);
q2.push(a[now]);
}
else{
q1.push(-a[now]);
}
}
else{
q1.push(-a[now]);
}
}
kth++;
int q1min = -q1.top(); q1.pop();
q2.push(q1min);
printf("%d
", q1min);
}
return 0;
}