题目来源: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 <stdio.h>
#include <queue>
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<int, vector<int>, less<int> > bigque;
priority_queue<int, vector<int>, greater<int> > 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;
}