Solution
经典的动态维护序列中位数问题。
采用对顶堆做法:维护一个大根堆和一个小根堆,其中大根堆维护当前序列中较小的一半元素,小根堆维护较大的一半元素。依次插入每个元素:
- 若当前元素小于小根堆堆顶,则插入大根堆。
- 若当前元素大于等于小根堆堆顶,则插入小根堆。
每插入一个元素,检查当前两个堆的大小之差是否超过 ,若超过
,则调整为相等大小。这样,每到序列有奇数位时,元素较多的堆的堆顶即为当前序列的中位数。
时间复杂度: 。
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
int s,t,n,x;
int fr(){
char ch;
int sum,sign=1;
while((ch=getchar())>'9'||ch<'0')
if(ch=='-')
sign=-1;
sum=ch-'0';
while((ch=getchar())>='0'&&ch<='9')
sum=(sum<<3)+(sum<<1)+ch-'0';
return sum*sign;
}
int main(){
t=fr();
while(t--){
s=fr(); n=fr();
printf("%d %d\n",s,n+1>>1);
priority_queue<int,vector<int>,greater<int> >q1;
priority_queue<int,vector<int>,less<int> >q2;
x=fr();
printf("%d ",x);
q1.push(x);
for(int i=2;i<=n;i++){
x=fr();
if(q1.top()>=x)
q2.push(x);
else
q1.push(x);
if(q1.size()>q2.size()+1){
q2.push(q1.top());
q1.pop();
}
else if(q1.size()+1<q2.size()){
q1.push(q2.top());
q2.pop();
}
if(i%2==1){
if(q1.size()>q2.size())
printf("%d ",q1.top());
else
printf("%d ",q2.top());
}
if(i%20==0)
printf("\n");
}
printf("\n");
}
return 0;
} 
京公网安备 11010502036488号