题目描述
Easy的学生的《数据结构》考试挂掉了,他求着Easy再给他一次机会,Easy出了这么一道题,如果他的学生做出来就给这个学生一次重新考试的机会,题目是这样的:
维护一个名为队列的数据结构,支持以下四种操作:
- ENQUEUE x
将值为x的元素放入队列的尾部
- DEQUEUE
输出当前队列首部的元素之后删除队列首部的元素
- MAX
输出当前队列中的最大值,若队列为空则输出”EMPTY!”(没有引号)
- MIN
输出当前队列中的最小值,若队列为空则输出”EMPTY!”(没有引号)
输入
包含多组测试数据
每组测试数据以一个整数N作为开始(0<=N<=500000)
当1<=N<=500000时,意味着会有N次队列操作,当N为0时意味着输入数据结束
如果1<=N<=500000之后会有N行,每行会有一条队列操作命令,分别是
1.ENQUEUE x
将值为x的元素放入队列的尾部
2.DEQUEUE
输出当前队列首部的元素之后删除队列首部的元素
3.MAX
输出当前队列中的最大值,若队列为空则输出”EMPTY!”(没有引号)
4.MIN
输出当前队列中的最小值,若队列为空则输出”EMPTY!”(没有引号)
请按命令进行相关队列操作或者输出
输出
对于每一组测试数据,第一行输出”Case X:”表示第X组数据(没有引号)之后
对每一个要求输出的操作进行输出,一个操作的输出占一行
样例输入
3
ENQUEUE 1
MAX
DEQUEUE
5
ENQUEUE 2
MAX
DEQUEUE
MIN
DEQUEUE
0
样例输出
Case 1:
1
1
Case 2:
2
2
EMPTY!
EMPTY!
题解:通过维护三个队列, 一个维护最大值, 一个维护最小值, 一个维护一般队列, 怎么维护最大值的和最小值的队列呢?
我们每插入一个元素时, 就要与队尾的元素比较, 如果插入的元素比队尾的元素大, 那么就删除现在队尾的元素,下一个队尾的元素比较,如果还比队尾大,再删了,再与新的队尾元素比较,如此循环往复,直到队列为空,或者队尾的元素要大于或等于插入的元素, 那么就将新元素插入队列尾部。如此一来这个队列就是一个从队首至队尾 永远单调递减的序列,队首即为max值。最小值队列就是反着来 维护一个 队首至队尾 永远单调递增的序列,队首即为min值。队列中的数据除了要储存它的值还要为其分配一个编号。为啥呢,因为还有出队操作啊,怎么判断,要出队的元素是否就是max队列和min队列队首的元素的,看其编号即可。
同时也熟练了一下双向队列的使用。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<cstdlib>
#include<string>
#define INF 0x3f3f3f3f
#define MAXM 16000000 + 10
#define MAXN 500000 + 10
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
pair<int , int > P[MAXN];
int main()
{
int n;
int cas = 1;
while(~scanf("%d", &n), n){
printf("Case %d:\n", cas ++);
deque<pair<int , int > > Q_up, Q_down, Q;
int cnt = 0;
for(int i = 0; i < n; i ++){
char op[10];
scanf("%s", op);
if(op[0] == 'E'){
scanf("%d", &P[cnt].first);
P[cnt].second = cnt;
Q.push_back(P[cnt]);
if(Q_up.empty()){
Q_up.push_back(P[cnt]);
}
else{
while(!Q_up.empty()){
if(P[cnt].first <= Q_up.back().first){
Q_up.push_back(P[cnt]);
break;
}
else
Q_up.pop_back();
}
if(Q_up.empty()){
Q_up.push_back(P[cnt]);
}
}
if(Q_down.empty())
Q_down.push_back(P[cnt]);
else{
while(!Q_down.empty()){
if(P[cnt].first >= Q_down.back().first){
Q_down.push_back(P[cnt]);
break;
}
else
Q_down.pop_back();
}
if(Q_down.empty()){
Q_down.push_back(P[cnt]);
}
}
}
if(op[0] == 'D'){
if(Q.empty()){
printf("EMPTY!\n");
continue;
}
if(Q.front().second == Q_up.front().second){
Q_up.pop_front();
}
if(Q.front().second == Q_down.front().second){
Q_down.pop_front();
}
printf("%d\n", Q.front());
Q.pop_front();
}
if(op[0] == 'M'){
if(op[1] == 'A'){
if(!Q_up.empty()){
printf("%d\n", Q_up.front().first);
}
else
printf("EMPTY!\n");
}
if(op[1] == 'I'){
if(!Q_down.empty()){
printf("%d\n", Q_down.front().first);
}
else
printf("EMPTY!\n");
}
}
cnt ++;
}
}
}
/*
The WAM is F**KING interesting .
*/