题解 UVA501 【Black Box】

思路与中位数一题,解决方案比较像,使用对顶堆来解决。

具体实现为,使用两个堆,大根堆维护较小的值,小根堆维护较大的值,即小根堆的堆顶是较大的数中最小的,大根堆的堆顶是较小的数中最大的。

将大于大根堆堆顶的数(比所有大根堆中的元素都大)的数放入小根堆,小于等于大根堆堆顶的数(比所有小根堆中的元素都小)的数放入大根堆。

那么就保证了所有大根堆中的元素都小于小根堆中的元素。

如果将大根堆中元素个数维护为(i)个,那么就可以直接访问大根堆堆顶,来得到从小到大的顺序排序后的第(i)个元素了。

(code):

#include<bits/stdc++.h>
#define maxn 200100
using namespace std;
priority_queue<int,vector<int>,less<int> > b;//大根堆
priority_queue<int,vector<int>,greater<int> > s;//小根堆
int n,m;
int a[maxn],u[maxn];
int cur=1,ii;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		cur=1;
		ii=0;
		while(!b.empty())
		b.pop();
		while(!s.empty())
		s.pop();
		memset(a,0,sizeof(a));
		memset(u,0,sizeof(u));//清空
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
		for(int i=1;i<=m;++i)
		scanf("%d",&u[i]);
		for(int i=1;i<=n;++i)
		{
			if(b.empty())//ADD命令
			s.push(a[i]);
			else
			{
				if(a[i]<b.top())
				{
					s.push(b.top());
					b.pop();
					b.push(a[i]);
				}
				else
				s.push(a[i]);
			}
			while(u[cur]==i)//GET命令
			{
				ii++;
				while(b.size()!=ii)//维护个数为i
				{
					int tmp=s.top();
					s.pop();
					b.push(tmp);
				}
				printf("%d
",b.top());
				cur++;
			}
		}
		if(t)
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lhm-/p/12229806.html