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

文章目录


【模板】队列

题目描述

题目解析

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

代码

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;
}

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

相关推荐
koddnty1 天前
数据结构:字符串匹配 kmp算法
算法
-一杯为品-1 天前
【足式机器人算法】#1 强化学习基础
算法·机器人
叫我詹躲躲1 天前
🌟 回溯算法原来这么简单:10道经典题,一看就明白!
前端·算法·leetcode
LAOLONG-C1 天前
LeetCode算法“无重复字符的最长子串”哈希表+滑动窗口+贪心
算法·哈希算法·散列表
hn小菜鸡1 天前
LeetCode 1023.驼峰式匹配
数据结构·算法·leetcode
不枯石1 天前
Matlab通过GUI实现点云的导向(引导)滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab
程序员三明治1 天前
二分查找思路详解,包含二分算法的变种,针对不同题的做法
java·数据结构·算法·二分查找
xiaoningaijishu1 天前
MATLAB中的Excel文件操作:从入门到精通
其他·算法·matlab·excel
未知陨落1 天前
LeetCode:67.寻找旋转排序数组中的最小值
数据结构·算法·leetcode
Gu_yyqx1 天前
快速排序总结
数据结构·算法·排序算法