【C++】一题弄懂队列

首先,普通的队列queue就不再赘述
普通队列queue讲解
讲述一下双端队列deque
其实这两者的本质类似

deque

插入元素

在队尾插入为push_back
在队首插入为push_front

输出元素

输出队首元素为q.front()
输出队尾元素为q.back()

弹出元素

弹出队首元素为q.pop_front()
弹出队尾元素为q.pop_back()

deque<int> q; //创建 deque
q.push_back(1); // 从队尾插入 1
q.push_front(2); // 从队头插入 2
cout << q.front() << endl; // 输出队头元素
cout << q.back() << endl; // 输出队尾元素
while(q.size()) // 清空 deque
    //q.pop_back();
    q.pop_front();

题面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

各个数组的作用

q[num] n u m num num的每个应用消息的位置
queue<pair<int, int> > timfirst为顺序,second为产生的应用
vis[i]为第i个是否访问过

queue<int> q[maxn]; // 队列数组 保存每个应用的未读消息
queue<pair<int, int> > tim; // 保存全部消息 first存顺序 second存由哪个应用产生
int vis[maxn]; // 保存消息的读取状态

op=1时

把当前长度+1,分别在第num个应用中加入和tim中,当前位置+1

		if(op == 1){
            ans += 1; 
            q[num].push(cnt);
            tim.push(make_pair(cnt, num));
            cnt++;
        }

op=2时

非常简单,把num应用的所有消息全部清除

		else if(op == 2)
        {
            while(!q[num].empty()) // 请填写判断条件
            {
                vis[q[num].front()]=true;
                q[num].pop();
                ans--;
            }
        }

op=3时

在读取前num条消息时,由于tim中入队位置是从小往大走的,所以如果当前位置比num大,那么后面所有都比num大,并且要保证tim里面还有元素
如果读到一条未读消息,那么应该把当前给改为已读,并且把未读消息数-1,还要注意应该要把q[num]首位元素弹出,因为q[num]的入队肯定是从小到大入队,而且tim也是,所以当前这位肯定是q[num]里最小的这位也是首位元素
,所以将其弹出。

		else
        {
         	// 读取前num条消息
            while(tim.size() && tim.front().first <= num)
            {
            	// 如果读到的是一条未读消息
                if(vis[tim.front().first]==false)
                {
                    vis[tim.front().first]=true;
                    ans--;
                    q[tim.front().second].pop();
                }
                tim.pop();
            }
        }

整体实现

#include<bits/stdc++.h>
using namespace std;
const int maxn =3e5+10;
int op, num;
int n, T;
queue<int> q[maxn]; // 队列数组 保存每个应用的未读消息
queue<pair<int, int> > tim; // 保存全部消息 first存顺序 second存由哪个应用产生
int vis[maxn]; // 保存消息的读取状态
int main()
{
    scanf("%d%d", &n, &T);
    int cnt = 1; // 消息列表的长度+1
    int ans = 0; // 未读消息的数量
    while(T--)
    {
        scanf("%d%d", &op, &num);
        if(op == 1)
        {
            ans += 1; 
            q[num].push(cnt);
            tim.push(make_pair(cnt, num));
            cnt++;
        }
        // 读取num应用产生的所有未读消息
        else if(op == 2)
        {
            while(!q[num].empty()) // 请填写判断条件
            {
                vis[q[num].front()]=true;
                q[num].pop();
                ans--;
            }
        }
        else
        {
         	// 读取前num条消息
            while(tim.size() && tim.front().first <= num)
            {
            	// 如果读到的是一条未读消息
                if(vis[tim.front().first]==false)
                {
                    vis[tim.front().first]=true;
                    ans--;
                    q[tim.front().second].pop();
                }
                tim.pop();
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值