看标题以为是区间第K大,准备去水一发,结果是整体第K大,由于没有删除操作,维护一个小根堆就行了,保持top是第k大,比top小的加入堆对top没有影响,也永远用不上,比top大的加入就更新top,保持堆有k个元素就行了。
数据结构没什么可以说的,主要是学习了STL的用法,用vector自带的堆函数,用优先队列,其实优先队列本身就是堆实现的。
不过还是不会手写堆,STL大法好。
下面是vector写的。
#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
#include<ctime>
#define pb push_back
#define pii pair<int,int>
#define LL long long int
using namespace std;
int main(){
int n,k,tmp;
char op;
while(scanf("%d%d%*c",&n,&k)!=EOF){
vector<int>H;
for(int i=0;i<k;++i){
scanf("%c %d%*c",&op,&tmp);
H.pb(tmp);
}
n-=k;
make_heap(H.begin(),H.end(), greater<int>() ); //把一个vector做成一个堆 STL自带的功能 greater<int>算子表示是一个小根堆
while(n--){
int top=*(H.begin()); //始终保持顶端是第K大就行了 题目说了询问一定合法
do{op=getchar();}while(op!='I'&&op!='Q');
if(op == 'I'){
scanf("%d%*c",&tmp);
if(tmp>top){ //比top小的对第K大没有影响 比top大的时候就更新top
pop_heap(H.begin(),H.end(), greater<int>() ); //删除元素 先用pop_heap维护堆 记得用greater算子维护小根堆
H.pop_back(); //再用pop_back删除元素
H.pb(tmp); //先把元素加入vector
push_heap(H.begin(),H.end(), greater<int>() ); //再用push_heap维护堆
}
}
else printf("%d\n",top);
}
}
}
优先队列写的。
#include<cstdio>
#include<queue>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
int main(){
int n,k,tmp;
char op;
while(scanf("%d%d%d",&n,&k)!=EOF)
{
priority_queue<int,vector<int>, greater<int> > q;
for(int i=0;i<k;++i){
scanf("%c %d%*c",&op,&tmp);
q.push(tmp);
}
n-=k;
while(n--){
scanf("%c%*c",&op);
if(op=='I'){
scanf("%d%*c",&tmp);
if(tmp>q.top()){
q.pop();
q.push(tmp);
}
}
else printf("%d\n",q.top());
}
}
}
可以看出优先队列比vector简便,不过以前不知道vector可以做堆,也算是学习了。
还有HDU的编译环境,大小算子是在functional头文件里面,这题就CE一发,我记得以前也用过,没什么问题来着,不过以后还是加上functional,以免CE冤枉。