我们以值建立一个大根堆,一个小根堆,假设我们现在的中位数是mid,那么用大根堆来储存小于等于mid的元素,用小根堆来储存大于mid的元素,然后读入数对其动态处理就行了
直接上代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
void clear2(priority_queue<int>& q) {
priority_queue<int> empty;
swap(empty, q);
}
void clear1(priority_queue<int, vector<int>, greater<int> >& p) {
priority_queue<int, vector<int>, greater<int> > empty;
swap(empty, p);
}
int n, m, num;
int main(){
scanf("%d", &n);
while(n--){
if(hh) printf("\n");
scanf("%d%d", &num, &m);
priority_queue<int> s1;//小根堆
priority_queue<int, vector<int>, greater<int> > s2;//大根堆
int mid, x;
printf("%d %d\n", num, (m+1)/2);//编号和中位数个数可以直接输出
scanf("%d", &mid);
printf("%d ", mid);//第一个读入的数定为mid,直接输出
for(int i=1; i<m; i++){//先读了第一个数所以i=1
if(i%20==0) printf("\n");
scanf("%d", &x);//读入数
if(x>mid) s2.push(x);
else s1.push(x);
if(i%2==0){//奇数个
if(s1.size()==s2.size()) { printf("%d ", mid);}//大小根堆的长度一样,中位数还是mid
else if(s1.size()>s2.size()) { s2.push(mid); mid=s1.top(); s1.pop(); printf("%d ", mid);}
//比mid小的数更多,先把mid压入小根堆,然后mid取大根堆的头,也就是现在的中位数,然后别忘了弹出大根堆的头,然后输出mid
else { s1.push(mid); mid=s2.top(); s2.pop(); printf("%d ", mid);}//同上
}
//printf("i=%d mid=%d %d %d\n",i,mid,s1.size(),s2.size());
//调试的语句
}
clear1(s2);//清除大小根堆
clear2(s1);//因为大小根堆的类型不同,要写两个清除函数
if(hh==0) hh=1;
}
return 0;
}
第一次发题解,如有不足,多多包涵^-^