POJ——1442(优先队列)

题目来源:http://poj.org/problem?id=1442

参考链接:https://blog.csdn.net/LYHVOYAGE/article/details/18360655

题目大意:给定M个数,每次可以插入序列一个数;再给N个数,表示在插入第几个数时输出一个数,第一次输出序列中最小的,第二次输出序列中第二小的……以此类推,直到输出N个数。

解题分析:创建两个优先队列,其中一个为降序队列命名为bigque,另一个为升序队列命名为smallque。升序队列起到一个筛选最小值的作用,所有的输入数据都要经过升序队列,然后不断从升序队列中取出其当前的最小值放入降序队列中。最后,在相应的时刻取出降序队列的头输出即可。以题目给定的这组数进行实例分析,给定的一组数为3 1 -4 2 8 -1000 2,要求在插入第 1 2 6 6 个数时,输出此时序列中最小的数。

(1)最开始时插入数据的个数为 0 < 1, 因此将第一个数3压入升序队列中,这时插入数据的个数 1 == 1。按照题目要求此时应该输出最小的,因为降序队列为空,所以取出升序队列的头即3压入降序队列中,这时输出降序队列的头 3

(2)将 1 压入升序队列中(此时升序队列里只有1),插入数据额个数为 2 == 2,应该输出降序队列中第二小的,但是降序队列的长度为1 < 2,因此取出升序队列的头即1压入降序队列中,这时输出降序队列的头 3

(3)将 -4 压入升序队列中,插入数据的个数为 3 < 6,因此继续向升序队列中压入2,8,-1000,则插入数据的个数满足6 == 6,这个时候升序队列中的数据顺序是-1000, -4, 2,8。当6==6时,按照规定需要输出第三小的数,但是降序队列的长度为2,因此取出升序队列的头-1000压入降序队列中,由于降序队列中的3 > 1 > -4,因此需要将3出队压入到升序队列中,此时输出第三小的数为1。

(4)接下来仍满足6==6,此时应该输出降序队列中第四小的数,但是降序队列的长度 < 4,因此升序队列将头出队即1,再压入降序队列中,最后输出的结果为1

代码如下:

#include 
#include 
using namespace std;
int data[30001];
int command[30000];
int main()
{
	int AddNum = 0;
	int GetNum = 0;
	scanf_s("%d%d", &AddNum, &GetNum);
	priority_queue, less > bigque;
	priority_queue, greater > smallque;
	for(int i = 0; i < AddNum; ++i)
	{
		scanf_s("%d", &data[i]);
	}
	for(int j = 0; j < GetNum; ++j)
	{
		scanf_s("%d", &command[j]);
	}
	int i = 0;
	int j = 0;
	size_t k = 1;
	int x = 0;
	while(j < GetNum)
	{
		if(i == command[j])
		{
			if(bigque.size() < k)
			{
				x = smallque.top();
				bigque.push(x);
				smallque.pop();
			}
			printf("%d\n", bigque.top());
			k++;
			j++;
		}
		else
		{
			if(bigque.size() < k)
			{
				smallque.push(data[i]);
				x = smallque.top();
				smallque.pop();
				bigque.push(x);
			}
			else if(bigque.top() > data[i])
			{
				x = bigque.top();
				bigque.pop();
				smallque.push(x);
				bigque.push(data[i]);
			}
			else
				smallque.push(data[i]);
			i++;
		}
	}

	return 0;
}

 

你可能感兴趣的:(ACM刷题)