题解 SP16254 【RMID2 - Running Median Again】

这是一道维护动态中位数的题,与SP15376不同的地方就是它给出的数字是没有顺序的,这一点很需要注意。

维护动态中位数,有两种做法,对顶堆链表+Hash ,在这里提供对顶堆的做法。

我们维护两个优先队列,一个大根堆和一个小根堆,在读入整个序列时,我们设当前的序列长度为 \(N\),我们始终要保持:

  1. 序列中从小到大排名为\(\,1\, \sim \,\left \lfloor \dfrac {N}{2} \right \rfloor\,\)的整数储存在大根堆中。

  2. 序列中从小到大排名为\(\,\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;
}
上一篇:code: 500, msg: server is DOWN now, please try again later!


下一篇:CF578D LCS Again