【题意】
小明和小宝正在玩数字游戏。游戏有n轮,小明在每轮中都可以写一个数,或者问小宝第k 大的数是什么(第k 大的数指有k -1个数比它大)。
游戏格式为:
请对小明的每个询问都给出第k 大的数。
【输入输出】
输入:
输入包含多个测试用例。每个测试用例的第1行都包含两个正整数n 、k (1≤k ≤n ≤1000000),表示n 轮游戏和第k 大的数。然后是n 行,格式为I c 或Q。
输出:
对每个询问Q,都单行输出第k 大的数。
【样例】
提示: 当写下的数字个数小于k 个时,小明不会问小宝第k 大的数。
【思路分析】
这道题数据范围很大,直接暴力肯定超时,因此可以借助优先队列实现。
【算法设计】
① 使用优先队列(最小值优先)存储最大的k 个数。
② 插入。若队中元素个数小于k ,则直接入队;若当前输入元素大于队头,则队头出队,当前元素入队。
③ 查询。队头(堆顶)就是第k 大的数,输出即可。
【举个栗子】
根据输入样例,操作过程如下。
① 插入。I 1:元素个数小于3,直接入队。I 2:元素个数小于3,直接入队。I 3:元素个数小于3,直接入队。
② 查询。查询第3大的数,队头1为第3大的数。数字3是第1大。
③ 插入。I 5:元素个数不小于3,5比队头大,则队头出队,5入队。
④ 查询。查询第3大的数,队头2为第3大的数。
⑤ 插入。I 4:元素个数不小于3,4比队头大,则队头出队,4入队。
⑥ 查询。查询第3大的数,队头3为第3大的数。
【算法实现】
#include
#include
#include //提供比较函数greater
#include
using namespace std;
int main(){
int i,n,k,num;
char c;
priority_queue<int,vector<int>,greater<int> >q;//小顶堆
while(~scanf("%d%d",&n,&k)){
while(q.size())//初始化队列为空
q.pop();
for(i=1;i<=n;i++){
cin>>c;
if(c=='I'){
scanf("%d",&num);
if(q.size()<k) //堆中元素个数小于k
q.push(num);
else if(q.top()<num) //当堆顶小于输入元素时
q.pop(),q.push(num);//堆顶出队,元素入队
} //堆中永远保存最大的k个元素
else
printf("%d\n",q.top()); //堆顶即为第k大元素
}
}
return 0;
}