【洛谷】队列相关经典算法题详解:模板队列、机器翻译、海港

文章目录


【模板】队列

题目描述

题目解析

本题非常简单,小编这里用数组模拟队列实现,需要两个下标分别标记队头和队尾。

代码

cpp 复制代码
using namespace std;
#include <iostream>

const int N = 1e6 + 10;
int qe[N];
int head = 0; //标记队头下标
int tail = 0; //标记队尾下标

int main()
{
	int n;
	cin >> n;
	int a, b;
	while (n--)
	{
		cin >> a;
		if (a == 1)
		{
			//队尾插入
			cin >> b;
			qe[tail++] = b;
		}
		else if (a == 2)
		{
			if (head == tail)
			{
				//队列为空
				cout << "ERR_CANNOT_POP" << endl;
			}
			else
			{
				++head;
			}
		}
		else if (a == 3)
		{
			if (head == tail)
			{
				//队列为空
				cout << "ERR_CANNOT_QUERY" << endl;
			}
			else
			{
				cout << qe[head] << endl;
			}
		}
		else
		{
			cout << tail - head << endl;
		}
	}

	return 0;
}

机器翻译

题目描述

题目解析

本题重在理解题意,内存的处理数据逻辑是先进先出,所以可以用一个队列来模拟内存。因为stl的队列不支持下标随机访问,所以需要开辟一个st数组用来映射标记队列中存放的数字。变量count记录查找词典次数,也就是数据入队列次数,遍历所有数字,若遇到的数字在队列中存在,则不做任何操作继续遍历,若遇到的数字在队列中不存在,则需要把数字入队列,并把当前数字对应st数组的下标置为true,若此时队列已经满了,还需要把队列pop一下,并把pop掉元素的数值对应st数组的下标置为false。最后输出count结果。

代码

cpp 复制代码
using namespace std;
#include <iostream>
#include <queue>

const int M = 1010;
//一个下标映射数组,标记某个值是否在队列中
bool st[M]; 

int main()
{
	int m, n;
	cin >> m >> n;

	queue<int> q;
	int x = 0; //暂存插入数据
	int count = 0; //标记插入队列次数
	while (n--)
	{
		cin >> x;
		//队列中没有x则插入x
		if (st[x] == false)
		{
			++count;
			//队列空间不足,pop一个数据后再插入数据
			if (q.size() >= m)
			{
				//pop同时把映射数组对应位置置为false
				st[q.front()] = false; 
				q.pop();
			}
			//队列空间足够,直接插入数据
			q.push(x);
			st[x] = true;
		}
	}
	cout << count;
	return 0;
}

海港

题目描述

题目解析

本题有一定难度,厘清思路还是很简单的。首先题目的信息很多,时间,船,人,国籍,我们最后要输出的是一定时间范围内有多少种国籍,而国家默认和人绑定,所以船只是一个载体,最主要要统计时间和人的信息,所以我们可以用一个pair手动将人和时间绑定。

根据题目描述一个国家有多少人是不确定的,所以可以用一个数组ctarr来统计某个国家的人数,数组下标代表国家,数组元素代表国家人数。

本题题意是以新来一艘船的时间为基准,统计离该时间最近的24小时内的国籍信息,也就是若船是在该时间24小时之前或者更早来的就不在统计范围内,要把这些数据去掉,并且时间是一直递增的,所以符合队列的先进先出原则,可以用队列来存储人和时间绑定的pair信息。

准备工作做完了,开始按船为单位读入数据,还需要用一个kind维护国籍信息。来一个人,就把它的时间和国籍打包存进queue,并把ctarr对应国籍加一,如果对应国籍元素是0,说明该人是当前时间范围内第一个该国籍的人,需要把kind加一。

读完一艘船的信息后,我们需要让队列合法,也就是清除在时间范围外的数据。遍历每一个在时间范围外的人,把该人ctarr对应国籍减一,如果对应国籍元素是1,需要把kind减一。最后输出kind信息。

代码

cpp 复制代码
using namespace std;
#include <iostream>
#include <queue>

typedef pair<int, int> PII;

const int N = 1e5 + 10;
//int st[N];
int ctarr[N];   //ctarr[i]表示i国家一共有多少人
int kind = 0;   //国家种类个数

int main()
{
	//queue存储每个人的信息,将人的信息和时间绑定
	//pair<人到港时间, 人国籍>
	queue<PII> q;
	//n艘船,船到达时间为t,船上有m个人,该人的国籍为k
	int n, t, m, k; 
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> t >> m;
		//遍历整艘船乘客
		for (int j = 0; j < m; j++)
		{
			cin >> k;
			q.push({ t, k }); //将人的信息插入队列
			//ctarr某个下标从0到1,国家种类个数加1
			if (ctarr[k] == 0)
				++kind;
			++ctarr[k]; //对应国籍人数加1
		}
		//让队列合法(队尾入,队头出,队尾-队头)
		while (q.back().first - q.front().first >= 86400)
		{
			pair<int, int> tmp = q.front();
			q.pop();
			//ctarr某个下标从1到0,国家种类个数减1
			if (ctarr[tmp.second] == 1)
				--kind;
			--ctarr[tmp.second];
		}
		cout << kind << endl;
	}
	return 0;
}

以上就是小编分享的全部内容了,如果觉得不错还请留下免费的关注和收藏
如果有建议欢迎通过评论区或私信留言,感谢您的大力支持。
一键三连好运连连哦~~

相关推荐
YuTaoShao3 小时前
【LeetCode 热题 100】49. 字母异位词分组
算法·leetcode·哈希算法
aliedudu5 小时前
决策树概念与原理
算法·决策树·机器学习
程序员Xu6 小时前
【LeetCode热题100道笔记】腐烂的橘子
笔记·算法·leetcode
天选之女wow6 小时前
【代码随想录算法训练营——Day4】链表——24.两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题02.07.链表相交、142.环形链表II
数据结构·算法·leetcode·链表
THMAIL7 小时前
量化基金从小白到大师 - 金融数据获取大全:从免费API到Tick级数据实战指南
人工智能·python·深度学习·算法·机器学习·金融·kafka
纪元A梦7 小时前
贪心算法应用:数字孪生同步问题详解
java·算法·贪心算法
纪元A梦7 小时前
贪心算法应用:食品生产线排序问题详解
算法·贪心算法
信奥卷王8 小时前
2024年9月GESPC++三级真题解析(含视频)
算法
望未来无悔9 小时前
系统学习算法 专题十八 队列+宽搜
java·算法