P1878 舞蹈课(详解)c++

news2025/5/13 2:13:53

题目链接:P1878 舞蹈课 - 洛谷 | 计算机科学教育新生态

1.题目解析

          

                                             

1:我们可以发现任意两个相邻的都是异性,所以他们的舞蹈技术差值我们都要考虑,4和2的差值是2,2和4的差值是2,4和3的差值是1,根据题目找到1这个最小差值后,输出这一对舞伴的编号即下标3和4,再输出队列里面还剩的另一队舞伴的编号1和2,这里成功出列了两对舞伴,所以先输出总对数2再输出3 4再输出1 2

                            

2.算法原理

解法:利用小根堆存所有相邻异性的差值,然后每次拿出最小的即可

                                                 

举个例子,把全部相邻异性的差值算出来之后,拿最小的差值,此时最小的差值是2,根据题目如果不止一对,那么最左边的那一对出列,所以让2号3号舞伴出列,接着继续让下一个差值最小的舞伴出列,这个想法很正确,就是利用堆存放相邻异性的差值,然后每次拿出最小的就行了,但是这个想法会很多问题                  

1.取出相邻的一对异性之后,他们的左右,有可能变成新的一对

比如现在让最小差值为2的一对舞伴出列,原来在他们左边的男生和右边的女生会组成一对新的舞伴,如何能做到快速地删除完一个之后,还能把左右两个连接起来呢,就可以利用双向链表存队列

                                                    

比如2和4舞伴出列后,让10指向7,7指向10就可以得到一个新队列,利用双向链表存队列,就可以实现删除一对舞伴后,只需修改指针,就可以快速地确定另一个,并且把新的队列还原出来

                                             

2.堆中,有可能存在已经出列的人
堆中存放这5个差值8 2 3 2 8,最小差值为2的一对舞伴出列后,1号和4号舞伴产生新的差值3,并把它放到堆里,2号,3号舞伴出列后,8和3就变成了无效元素,但它们还在堆里,此时我拿出3,再输出下标,就有可能出错,所以要杜绝这种情况,创建一个bool数组标记一下即可;true表示出列,false表示没出列,假如我把3拿出来,再判断他对应的舞伴3和4是否有出列的情况,如果有就不对这个3进行处理

3.堆中存什么?
我们要知道技术差以及左边的人是谁以及右边的人是谁,<技术差,左编号,右编号>,这样就能还原双向链表,把技术差拿到,知道左编号和右编号,通过修改指针就可以还原

代码

//舞蹈课
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>

using namespace std;

const int N = 2e5 + 10;

int n;
int s[N]; //标记男女 - 1/0

//双向链表存数据
//数据是从左向右依次进来的,4的右边就是2,2的左边就是4,
//直接把它定义出来就行了,就不需要h,id这些指针了
int e[N];
int pre[N], ne[N];

struct node {
	int d; //技术差
	int l, r; //左右编号

	//小根堆,大元素下坠 
	bool operator <(const node& x) const
	{
		//根据题目如果不止一对,那么最左边的那一对出列
		//可以知道技术差有可能相等,所以技术差相等的时候可以根据左编号定义小根堆
		if (d != x.d) return d > x.d;
		else return l > x.l;
	}
};

priority_queue<node> heap;
bool st[N]; //标记已经出列的人

int main()
{
	cin >> n; 
	for (int i = 1; i <= n; ++i)
	{
		char ch; cin >> ch;
		if (ch == 'B') s[i] = 1;
	}

	for (int i = 1; i <= n; ++i)
	{
		cin >> e[i];
		//直接创建双向链表
		pre[i] = i - 1;
		ne[i] = i + 1;
	}
	ne[n] = 0; //0表示后面没有元素

	//1.先把所有的异性放进堆里
	for (int i = 2; i <= n; ++i)
	{
		//如果当前性别和前一个人的性别不一样
		if (s[i] != s[i - 1])
		{
			heap.push({ abs(e[i] - e[i - 1]), i - 1, i });
		}
	}

	//2.提取结果
	//我们最后要先输出有多少对出列,所以要先把结果存起来
	vector<node> ret; //暂存结果

	//堆里还要异性就一直出列
	while (heap.size())
	{
		node t = heap.top(); heap.pop();
		int d = t.d, l = t.l, r = t.r;
		//l、r其中任何一个标记ture,说明对应的位置里有人已经出列了
		if (st[l] || st[r]) continue;

		ret.push_back(t);
		st[l] = st[r] = true; //标记l或r已经出列

		//维护双向链表
		ne[pre[l]] = ne[r];
		pre[ne[r]] = pre[l];
		
		//判断新的左右是否会成为一对,左和右有可能不存在,判断异性就无意义
		//如果l的编号是1,1的左边是不存在人的,所以也要判断l/r是否存在
		int left = pre[l], right = ne[r];
		if (left && right && s[left] != s[right])
		{
			heap.push({ abs(e[left] - e[right]), left, right });
		}
	}

	cout << ret.size() << endl;	
	for (auto& x : ret)
	{
		cout << x.l << " " << x.r << endl;
	}

	return 0;
}

也可以用pair存结果

	//暂存结果
	vector<pair<int, int>> ret;

	//模拟出列过程
	while (heap.size())
	{
		node t = heap.top(); heap.pop();
		int d = t.d, l = t.l, r = t.r;

		if (st[l] || st[r]) continue; //对应舞伴已出列则不处理

		//记录结果
		ret.push_back({ l,r }); 
		st[l] = st[r] = true; //标记已出列

		//更新双向链表
		int left = pre[l], right = ne[r];
		ne[left] = right;
		pre[right] = left;

		//检查新的相邻是否为异性组合
		//l和r如果是1或者n,那便没有左边人或右边人
		if (left && right && s[left] != s[right])
		{
			heap.push({ abs(e[left] - e[right]), left , right });
		}
	}

	cout << ret.size() << endl;
	for (auto& x : ret)
	{
		cout << x.first << " " << x.second << endl;
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2298420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++学习篇】C++11

目录 ​编辑 1. 初始化列表{} 1.1 C98中的{} 1.2 C11中的{} 2. C11中的std::initializer_list 3. 右值引用和移动语义 3.1 左值和右值 3.2 左值引用和右值引用 3.3 引用延长生命周期 3.4 左值和右值的参数匹配 3.5 右值引⽤和移动语义的使⽤场景 3.5.1 左值引⽤…

Vulnhub靶机随笔-Hackable II

Vulnhub靶机Hackable II详解 攻击机Kali IP:192.168.1.6 靶机 IP:未知 系统:未知 A.信息收集 扫描靶机存活性 确定IP地址 1.命令:arp-scan -l 扫描靶机开放端口及其服务版本信息 2.命令:nmap -A -p- -sV 靶机IP 3.靶机开放三个端口: 21ftp端口:存在anonymous匿…

九.Spring Boot使用 ShardingSphere + MyBatis + Druid 进行分库分表

文章目录 前言一、引入依赖二、创建一个light-db_1备用数据库三、配置文件 application-dev.yml四、创建shardingsphere-config.yml完整项目结构 五、测试总结 前言 在现代化微服务架构中&#xff0c;随着数据量的不断增长&#xff0c;单一数据库已难以满足高可用性、扩展性和…

【第2章:神经网络基础与实现——2.3 多层感知机(MLP)的构建与调优技巧】

在当今科技飞速发展的时代,人工智能早已不是一个陌生的词汇,它已经渗透到我们生活的方方面面,从智能语音助手到自动驾驶汽车,从图像识别到自然语言处理。而支撑这一切的核心技术之一,就是神经网络。作为机器学习领域的璀璨明星,神经网络已经在众多任务中取得了令人瞩目的…

宠物企业宣传网站静态模板 – 前端静态页面开发实例

该宠物宣传企业站是一个基于前端技术构建的静态网站&#xff0c;旨在为宠物行业的企业提供一个简洁、现代的在线展示平台。整个网站采用HTML、CSS和JavaScript三种技术&#xff0c;确保了良好的用户体验和页面表现。 前端技术&#xff1a; HTML&#xff1a;HTML负责构建网站的…

【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)——4.2 LSTM的引入与解决长期依赖问题的方法】

在人工智能的璀璨星空中,深度学习模型犹如一颗颗耀眼的星辰,引领着技术的革新。而在处理序列数据的领域中,循环神经网络(RNN)无疑是那颗最为亮眼的星星。然而,即便是这样强大的模型,也面临着一些棘手的问题,其中最突出的便是长期依赖问题。今天,我们就来深入探讨一下长…

el-input输入框样式修改

el-input输入框样式修改 目的&#xff1a;蓝色边框去掉、右下角黑色去掉(可能看不清楚) 之前我试过deep不行 最有效的办法就是就是在底部添加一下css文件 代码中针对input的type为textarea&#xff0c;对于非textarea&#xff0c;只需将下面的css样式中的textarea替换成input…

日常问题-pnpm install执行没有node_modules生成

日常问题-pnpm install执行没有node_modules生成 1.问题2.解决方法 1.问题 执行pnpm i后&#xff0c;提示Scope: all 3 workspace projects Done in 503ms&#xff0c;而且没有node_modules生成。很奇怪 2.解决方法 确保根目录有 pnpm-workspace.yaml 文件&#xff1a; 把这…

C++-----------酒店客房管理系统

酒店客房管理系统 要求&#xff1a; 1.客房信息管理:包括客房的编号、类型、价格、状态等信息的录入和修改; 2.顾客信息管理:包括顾客的基本信息、预订信息等的管理; 3.客房预订:客户可以根据需要进行客房的预订&#xff0c;系统会自动判断客房的可用情况; 4.入住管理:客户入住…

ORDER BY盲注攻击:原理、实现与防御(附Python多线程爆破脚本)

引言 在SQL注入攻击中&#xff0c;ORDER BY注入是一种容易被忽视但危害极大的漏洞类型。与传统的UNION或WHERE注入不同&#xff0c;ORDER BY参数通常无法直接返回查询结果&#xff0c;攻击者需要依赖**盲注&#xff08;Blind SQLi&#xff09;**技术逐字符提取数据。本文将结合…

人工智能在临床应用、药物研发以及患者护理等方面的最新研究进展|顶刊速递·25-02-12

小罗碎碎念 推文速览 第一篇文章提出 CRAFT-MD 框架评估临床大语言模型&#xff08;LLMs&#xff09;在医患互动任务中的表现&#xff0c;发现其存在局限性&#xff0c;并基于结果给出改进评估的建议。 第二篇文章全面阐述了 2019 年以来人工智能在小分子药物研发全流程&#…

【物联网】电子电路基础知识

文章目录 一、基本元器件1. 电阻2. 电容3. 电感4. 二极管(1)符号(2)特性(3)实例分析5. 三极管(1)符号(2)开关特性(3)实例6. MOS管(产效应管)(1)符号(2)MOS管极性判定(3)MOS管作为开关(4)MOS管vs三极管7. 门电路(1)与门(2)或门(3)非门二、常用元器件…

辛格迪客户案例 | 钥准医药科技GMP文件管理(DMS)项目

01 创新药企&#xff0c;崛起于启东 在我国医药行业蓬勃发展的浪潮中&#xff0c;钥准医药科技&#xff08;启东&#xff09;有限公司&#xff08;以下简称“钥准医药”&#xff09;犹如一颗冉冉升起的新星&#xff0c;闪耀着创新与活力的光芒。成立于2015年&#xff0c;钥准医…

Day65_20250213图论part9_dijkstra(堆优化版)|Bellman_ford算法精讲

Day65_20250213图论part9_dijkstra(堆优化版)|Bellman_ford算法精讲 dijkstra(堆优化版) 题目 https://www.programmercarl.com/kamacoder/0047.%E5%8F%82%E4%BC%9Adijkstra%E5%A0%86.html 小明参加科学大会 思路 思路 朴素版的dijkstra&#xff0c;时间复杂度为O(n^2)&am…

w208基于spring boot物流管理系统设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

望远镜成像系统--科学评价光学镜头

望远镜是一种利用透镜或反射镜以及其他光学器件观测遥远物体的光学仪器。其原理是通过透镜的折射或反射镜的反射&#xff0c;将光线聚焦成像&#xff0c;再经过一个放大目镜进行观察。日常生活中的光学望远镜又称“天文望远镜”。1608年&#xff0c;荷兰的一位眼镜商汉斯利伯希…

产品更新 | 华望M-Design 平台的AI 建模功能即将上线

前言 在 AI 技术加速发展的背景下&#xff0c;杭州华望系统科技有限公司在⼤语⾔模型与 SysML 标准进行深度结合的基础上&#xff0c;强力推出AI建模功能。该功能⽀持⽤户通过上传⽂档或对话交互等⽅式完成需求智能增强、模型动态构建与细节补充、实时获取结构化反馈等业务。⽬…

RabbitMQ 在 Spring Boot中使用方式

文章目录 作用MQ docker 安装MQ使用RabbitMQ的整体架构及核心概念&#xff1a;RabbitMQ的整体架构及核心概念&#xff1a;消费者消息推送限制交换机与队列## 项目使用MQDirect: 直连模式Fanout: 广播模式Topic: 主题模式Headers: 头信息模式 使用DEMO地址异常问题记录 作用 Ra…

HAL库框架学习总结

概述&#xff1a;HAL库为各种外设基本都配了三套 API&#xff0c;查询&#xff0c;中断和 DMA。 一、HAL库为外设初始化提供了一套框架&#xff0c;这里以串口为例进行说明&#xff0c;调用函数 HAL_UART_Init初始化串口&#xff0c;此函数就会调用 HAL_UART_MspInit&#xff0…

深入解析系统调用接口(System Call Interface, SCI)

在操作系统的世界中&#xff0c;用户态应用程序无法直接访问内核态资源&#xff0c;而必须通过一种受控的方式进行交互。这种方式就是系统调用&#xff08;System Call&#xff09;。系统调用接口&#xff08;System Call Interface, SCI&#xff09;是用户程序与操作系统内核之…