1239: Easy的队列 (单调队列)

题目描述
Easy的学生的《数据结构》考试挂掉了,他求着Easy再给他一次机会,Easy出了这么一道题,如果他的学生做出来就给这个学生一次重新考试的机会,题目是这样的:

维护一个名为队列的数据结构,支持以下四种操作:

  1. ENQUEUE x

将值为x的元素放入队列的尾部

  1. DEQUEUE

输出当前队列首部的元素之后删除队列首部的元素

  1. MAX

输出当前队列中的最大值,若队列为空则输出”EMPTY!”(没有引号)

  1. 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 .

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值