[luogu1168]中位数_优先队列

中位数

    题目大意:输出读入的前2*k+1个数的中位数。一共有n个数,按照读入顺序。

    注释:$1\le n \le 10^9$。

      想法:这是优先队列的一个应用qwq。我们弄两个堆。小根堆和大根堆,保证:大根堆中的任意一个数都小于小根堆,而且大根堆中的元素个数始终比小根堆大且只大1。最后我们只需要输出大根堆的对顶即可。具体地:我们对于每一个新读入的元素和原本合法的大、小根堆进行操作,将当前元素和大根堆对顶进行比较,如果当前元素大于大根堆对顶,我们就将其扔进小根堆,反之,扔进大根堆,显然是正确的。在维护大、小根堆的数目时,我们通过循环处理,无非就是讲大、小根堆的堆顶倒来倒去。

    最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
priority_queue<int>q1;
priority_queue<int,vector<int>,greater<int> >q2;
// int a[100100];
int main()
{
	int n;
	scanf("%d",&n);
	int sum_for_Big=0;//大根堆数目
	int sum_for_Small=0;//小根堆数目
	for(int i=1;i<=n;i++)
	{
		int a;
		scanf("%d",&a);
		if(i==1)
		{
			sum_for_Big=1;
			q1.push(a);
			sum_for_Small=0;
			printf("%d\n",a);
		}
		else
		{
			if(a<q1.top())//插入元素
			{
				q1.push(a);
				sum_for_Big++;
			}
			else q2.push(a),sum_for_Small++;
			if(i%2==1)
			{
				while(sum_for_Big-sum_for_Small!=1)//维护大、小根堆的数目关系
				{
					if(sum_for_Big<sum_for_Small)
					{
						int x=q2.top();
						q2.pop();
						sum_for_Small--;
						q1.push(x);
						sum_for_Big++;
					}
					else
					{
						int x=q1.top();
						q1.pop();
						sum_for_Big--;
						q2.push(x);
						sum_for_Small++;
					}
				}
				printf("%d\n",q1.top());
			}
		}
	}
	// printf("%d %d\n",sum_for_Big,sum_for_Small);
	// printf("%d\n",q1.top());
	// printf("%d\n",q2.top());
	return 0;
}/*
3 1 3 5
*/

     小结:priority的应用,好像suika学长说heap比这鬼东西快一万倍... ...

posted @ 2018-03-26 10:42  JZYshuraK_彧  阅读(251)  评论(0编辑  收藏  举报