这是一道维护动态中位数的题,与SP15376不同的地方就是它给出的数字是没有顺序的,这一点很需要注意。
维护动态中位数,有两种做法,对顶堆和链表+Hash ,在这里提供对顶堆的做法。
我们维护两个优先队列,一个大根堆和一个小根堆,在读入整个序列时,我们设当前的序列长度为 \(N\),我们始终要保持:
-
序列中从小到大排名为\(\,1\, \sim \,\left \lfloor \dfrac {N}{2} \right \rfloor\,\)的整数储存在大根堆中。
-
序列中从小到大排名为\(\,\left \lfloor \dfrac {N}{2} \right \rfloor + 1\, \sim \,N\,\) 的整数储存在小根堆中。
在任何时候,如果在加入一个数后导致某个堆中的元素过多而打破了这个平衡,我们就需要将这个堆的堆顶取出并插入另一个堆。
这样一来我们可以很容易的得知:
-
当\(\,M\,\)为奇数时,小根堆的堆顶即为所求的中位数。
-
当\(\,M\,\) 为偶数时,大根堆的堆顶即为所求的中位数。
\(Code\):
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define vocaloid(v) (v>='0'&&v<='9')
template <typename T>
il void read(T &x)
{
x=0;int flag=1;char v=getchar();
while(!vocaloid(v)) {if(v=='-') flag=-1;v=getchar();}
while(vocaloid(v)) {x=(x<<1)+(x<<3)+v-'0';v=getchar();}
x*=flag;
}
int x,len,mid,T;
priority_queue <int,vector<int>,less<int> > q1;//降序 大根堆
priority_queue <int,vector<int>,greater<int> > q2;//升序 小根堆
int main()
{
read(T);
while(T--)
{
while(scanf("%d",&x)==1)
{
if(x==0)
{
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
len=0;
break ;
}
if(x==-1)
{
if(len%2==0) printf("%d\n",q1.top()),q1.pop();
else printf("%d\n",q2.top()),q2.pop();
len--;
}
else
{
if(q2.empty()||x>q2.top()) q2.push(x),len++;
else q1.push(x),len++;
}
while(q1.size()>q2.size()) q2.push(q1.top()),q1.pop();
while(q2.size()>q1.size()+1) q1.push(q2.top()),q2.pop();
}
}
return 0;
}