Easy的队列,模拟队列进出并求最大最小值,

本文介绍了一种高效的数据结构实现方法,用于处理队列的基本操作及最大最小值的快速查询。通过维护三个队列,能够实现在大量数据输入的情况下,依然保持较快的查询速度。

1239: Easy的队列

时间限制: 2 Sec  内存限制: 1024 MB
提交: 87  解决: 19
[提交][状态][讨论版][命题人:admin]

 

题目描述

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

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

1. ENQUEUE x

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

2. DEQUEUE

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

3. MAX

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

4. 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!

 

模拟队列进出很简单,重要的是找最大最小值,每次都查询一遍会超时,所以要维护两个序列;

一共维护三个队列,一个正常模拟进出,一个维护最大值,插入元素x的时候与队尾比较,如果x大于队尾元素,

直接将队尾元素扔掉,不会影响结果,因为先入队的先出队,x比前面的元素大并且比他们后入队,所以x后出队,所以在他前面并且比他小的元素存不存在都不影响结果,另一个维护最小值,与之类似;

另外。一定要用printf和scanf,用cin和cout会超时;

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <list>
using namespace std;
typedef long long ll;
 
int main( )
{
    std::ios::sync_with_stdio(false);
    int n;
    int k = 1;
    while(cin >> n&&n){
        printf("Case %d:\n",k++);
        deque<int> a,b,c;//双端队列,队首队尾都可以插入或删除元素;
//a是正常队列,b是最大值队列,c是最小值队列
        char  s[20];
        int x;
        while(n--){
            cin >> s;
            if(s[0] == 'E'){
                cin>>x;
                a.push_back(x);
                while(b.size() && b.back()<x){
                    b.pop_back();
                }
                b.push_back(x);
                while(c.size() && c.back()>x){
                    c.pop_back();
                }
                c.push_back(x);
            }
            else if(s[0] == 'D'){
                if(!a.size())  printf("EMPTY!\n");
                else{
                    if(b.size() && b.front() == a.front()) b.pop_front();
                    if(c.size() && c.front() == a.front()) c.pop_front();
                    printf("%d\n",a.front());
 
                    a.pop_front();
                }
            }
            else{
                    if(!a.size()) printf("EMPTY!\n");
            else{
                if(s[1] == 'A') printf("%d\n",b.front());
                else printf("%d\n",c.front());
            }
            }
        }
    }
    return 0;
}
 

 

本题 easy 版本与 hard 版本的唯一区别为数据范围的不同,你通过 hard 版本即可通过 easy 版本。 小柒最近迷恋于区间选数游戏,这天她抓到了你上课玩手机不听课,于是决定和你玩一把游戏,如果你答对了她的问题,那么她就不向任课老师告状。 游戏的规则是这样的:给出一个长度为 n 的数组(编号从 1~n)和一个整数 k,你和小柒轮流选数,从 1 到 n 依次选索引 i 记录序列 [amax(1,i-k+1), amax(2,i-k+2), ……, ai],小柒的回合会从序列中最大放入自己的集合 A,你的回合会从序列中最小值放入自己的集合 B,游戏由小柒先选(她要向你示范选数的规则)。 在完成所有 n 轮选数之后,小柒要你回答每个人集合中都存在哪些数(集合中可能存在数值相等的数)出它们的和。 输入 第一行包含两个整数 n,k(1 ≤ k ≤ n ≤ 105),代表数组的长度以及需要记录的区间的长度; 第二行包含 n 个整数 ai(1 ≤ ai ≤ 109)。 输出 第一行包含两个整数 s,w,分别代表集合 A 中所有整数的和以及集合 B 中所有整数的和; 第二行包含 c 个整数,分别代表集合 A 中所有的数; 第三行包含 d 个整数,分别代表集合 B 中所有的数。 注意:集合 A 与集合 B 中的整数你需要按照数值从小到大的顺序输出,每两个整数之间用一个空格隔开。 样例输入 Copy 6 3 1 3 5 2 4 6 样例输出 Copy 11 5 1 5 5 1 2 2c++
最新发布
03-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值