是一道好题,这个题目一开始有一个O(n^2)的做法,就是O(n)遍历的基础上用快排O(n)的思想找第k大,总的时间复杂度O(n^2),应该会超时。
有一个更好的做法的维护两个堆,一个大根堆维护一堆小的数,小根堆维护一些大的数使得它们呈现一个有序的(递增),这个还是比较好想到,我是卡在怎么维护上面了,就是为了使得这两个堆呈递增,他们数量应该是差不多的也就是最多差一个1,就是这边放一个那边放一个,这样就行了,但是这样放不是有序的,有序的当且仅当大堆顶<=小根堆堆顶。如果破坏了一个平衡就交换,这样就可以维护好这两个堆了。
(输入要用scanf不然会被卡,输出格式也需要注意一下)
代码
#include<bits/stdc++.h> using namespace std; void solved(){ int t;scanf("%d",&t); while(t--){ int id,n;scanf("%d%d",&id,&n); printf("%d %d\n",id,(n + 1) / 2); priority_queue<int,vector<int>,greater<int> >p2;//小根堆 priority_queue<int,vector<int>,less<int> >p1;//大根堆 int cnt = 0; for(int i = 1; i <= n; i++){ int a;scanf("%d",&a); if(p1.size() > p2.size())p2.push(a); else p1.push(a); if(p2.size() > 0 && p1.top() > p2.top()){ int t = p2.top();p2.pop(); p2.push(p1.top());p1.pop(); p1.push(t); } if(i & 1){ if(p1.size() > p2.size())printf("%d ",p1.top()); else printf("%d ",p2.top()); if (i % 20 == 19 && i != n) printf("\n"); } } printf("\n"); } } int main(){ solved(); return 0; }