现在的位置: 首页 > 综合 > 正文

POJ 1442 堆

2013年08月09日 ⁄ 综合 ⁄ 共 2458字 ⁄ 字号 评论关闭

仿照:http://www.2cto.com/kf/201106/92643.html
题意:给出两种操作:ADD(x),将x添加到有序列表中;GET()返回全局迭代器所指的值,其中迭代器在GET操作后会自添加1
题解:大顶堆和小顶堆。
    其中,对于序列S[1..n],及表示迭代器位置的index,大顶堆维护排序后的S[1..index-1],小顶堆维护排序后的S[index..n],
例如S[1..n] = 1,2,3,4,5,6,7,index = 4,则大顶堆为{1,2,3},小顶堆为{4,5,6,7}为什么要这样维护呢?因为当小堆最小的元素都大于大堆最大的元素时,那么序列中排第index个数就是小堆最小的数了。
   我们假设第k趟GET()后,有以下情景(GET后k自动加1):大顶堆:S[1..k],堆顶元素为S[k],小顶堆:S[k+1,n],堆顶元素为S[k+1],然后每当添加一个元素newE时,先添加到大顶堆中,这时如果出现大顶堆数大于小顶堆的数时,理应交换。

#include <iostream>
#include <queue>
using namespace std;

#define M 30005
int array[M];

priority_queue< int,vector<int>,less<int> > maxHeap;
priority_queue< int,vector<int>,greater<int> > minHeap;

int main()
{
	int n, m, i;
	scanf("%d%d",&n,&m);
	for ( i = 0; i < n; ++i )
		scanf("%d",array+i );

	int oper = 0, k = 0, t1, t2;
	for ( i = 0; i < m; ++i )
	{
		scanf("%d",&oper);
		while ( k < oper )
		{
			minHeap.push ( array[k] );
			if ( ! maxHeap.empty() && minHeap.top() < maxHeap.top() )
			{
				t1 = minHeap.top(); minHeap.pop();
				t2 = maxHeap.top(); maxHeap.pop();
				maxHeap.push(t1); minHeap.push(t2);
			}
			++k;
		}
		printf("%d\n",minHeap.top());
		maxHeap.push ( minHeap.top() );
		minHeap.pop();
	}
	return 0;
}

下面是手工实现堆:

#include <iostream>
using namespace std;

const int M = 30005;
int array[M];

struct min_Heap
{
	int hp[M], size;
	void siftDown ( int start, int m )
	{
		int i = start, j = 2 * i + 1;
		int temp = hp[i];
		while ( j <= m )
		{
			if ( j < m && hp[j] > hp[j+1] ) ++j;
			if ( temp <= hp[j] ) break;
			else { hp[i] = hp[j]; i = j; j = j * 2 + 1; }
		}
		hp[i] = temp;
	}

	void siftUp ( int start )
	{
		int j = start, i = ( j - 1 ) / 2;
		int temp = hp[j];
		while ( j > 0 )
		{
			if ( temp >= hp[i] ) break;
			else { hp[j] = hp[i]; j = i; i = ( i - 1 ) / 2; }
		}
		hp[j] = temp;
	}

	void insert ( const int x )
	{
		hp[size] = x;
		siftUp ( size );
		size++;
	}

	void del ()
	{
		hp[0] = hp[size-1];
		size--;
		siftDown ( 0, size-1 );
	}

	int getSize ()
	{
		return size;
	}
} minHeap;

struct max_Heap
{
	int hp[M], size;
	void siftDown ( int start, int m )
	{
		int i = start, j = 2 * i + 1;
		int temp = hp[i];
		while ( j <= m )
		{
			if ( j < m && hp[j] < hp[j+1] ) ++j;
			if ( temp >= hp[j] ) break;
			else { hp[i] = hp[j]; i = j; j = j * 2 + 1; }
		}
		hp[i] = temp;
	}

	void siftUp ( int start )
	{
		int j = start, i = ( j - 1 ) / 2;
		int temp = hp[j];
		while ( j > 0 )
		{
			if ( temp <= hp[i] ) break;
			else { hp[j] = hp[i]; j = i; i = ( i - 1 ) / 2; }
		}
		hp[j] = temp;
	}

	void insert ( const int x )
	{
		hp[size] = x;
		siftUp ( size );
		size++;
	}

	void del ()
	{
		hp[0] = hp[size-1];
		size--;
		siftDown ( 0, size-1 );
	}

	int getSize ()
	{
		return size;
	}
} maxHeap;

int main()
{
	int n, m, i;
	scanf("%d%d",&n,&m);
	for ( i = 0; i < n; ++i )
		scanf("%d",array+i);

	int oper, t1, t2, k = 0;
	minHeap.size = maxHeap.size = 0;
	for ( i = 0; i < m; ++i )
	{
		scanf("%d",&oper);
		while ( k < oper )
		{
			minHeap.insert(array[k]);
			if ( maxHeap.getSize() != 0 && minHeap.hp[0] < maxHeap.hp[0] )
			{
				t1 = minHeap.hp[0]; minHeap.del();
				t2 = maxHeap.hp[0]; maxHeap.del();
				minHeap.insert(t2); maxHeap.insert(t1);
			}
			++k;
		}
		printf("%d\n",minHeap.hp[0]);
		maxHeap.insert(minHeap.hp[0]);
		minHeap.del();
	}
	return 0;
}

抱歉!评论已关闭.