题目大意:对于每组测试数据,有奇数个数,这些数会一个一个的输入,我们需要在每次数字个数为奇数的时候输出当前的中位数。
如果我们每次求中位数都去进行快排,那输入n个数,就会进行(n+1)/2次排序,时间复杂度是O(n2logn),无法通过本题。
如果我们维护两个堆,一个大根堆,一个小根堆,大根堆中存较小的一半数,小根堆存较大的一半数。每次输入一个数,如果它比小根堆顶部的数大,我们就把x插入小根堆,否则就插入大根堆。
每次插入我们需要将两个堆中的元素数量平均,使小根堆中的元素数量等于大根堆中的元素数量或+1。这样,每次的答案就是小根堆的堆顶。
#include<bits/stdc++.h>
using namespace std;
void solve(){
int id,n;
scanf("%d%d",&id,&n);
priority_queue<int>q1;//大根堆
priority_queue<int,vector<int>,greater<int>>q2;//小根堆
vector<int>ans;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(q2.empty()||x>=q2.top())q2.push(x);
else q1.push(x);
while(q1.size()>q2.size()){
int xx=q1.top();q1.pop();
q2.push(xx);
}
while(q2.size()>q1.size()+1){
int xx=q2.top();q2.pop();
q1.push(xx);
}
if(i&1)ans.push_back(q2.top());
}
printf("%d %d\n",id,n/2+1);
for(int i=0;i<ans.size();i++){
printf("%d ",ans[i]);
if(i%10==9)puts("");
else if(i==ans.size()-1)puts("");
}
}
int main(){
int p;
scanf("%d",&p);
while(p--)solve();
return 0;
}