看标题以为是区间第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冤枉。