【2024.2.5练习】砍竹子(25分)

news2024/9/22 4:47:18

题目描述


题目分析

考虑题目是否满足贪心。每次施展魔法会使一段连续的竹子高度变为一半左右的平方根。根据样例,似乎每次让最高的竹子变短就能得到最优解。

假设魔法一次只能对一根竹子使用,永远不出现连续相同高度的竹子,那么显然无论使用魔法的顺序如何,使用次数永远都是固定的;如果会出现连续相同的竹子,先对这排竹子中最高的施展魔法不会对其他竹子的变短次数造成影响。而如果率先对相同高度且不是最高的竹子变短,则可能会丧失更多竹子变成连续的机会,故贪心策略成立。

接下来是如何检测最高竹子和连续相同竹子,如何设计算法是难点。首先想到采用map容器给竹子高度排序,排序过程的复杂度为O(nlogn),不会超时;然后使用深度优先搜索检测最大竹子两个方向上所有相同连续的竹子,让这些竹子一起变短。经计算最大高度的竹子最多经过6次变短高度就能变成1,因此魔法的最多施展次数约为10^6次,如果每次都经过一遍搜索会超时。

为了避免重复检测连续的竹子,对DFS进行改良,每次搜索到连续竹子,在搜索过的竹子上分别添加s\t标记,标志从第s根到第t根的竹子都是相同高度的,从复杂度上将所有相同高度的连续竹子化为一根,差不多是某种程度上的离散化,免去了重复的搜索。


我的代码

long long型数据的范围是9\times 10^{18},可以用来记录竹子的高度。敲了几行代码后发现只用一个dfs很难处理已经搜索过的竹子,因此使用两个dfs,分别向左和向右搜索。

在代码过程中由于不熟悉stl容器语法踩了很多坑:比如迭代器的失效问题;以及multimap.erase(key)会将对应的所有value都删除。

#include <iostream>
#include <algorithm>
#include <map>
#include <stack>
#include <math.h>

using namespace std;
typedef long long ll;
int n; //总竹子个数
ll lenth[200002]; //所有竹子高度
int sign[200002][3]; //sign[n][0]和sign[n][1]分别储存了连续竹子的起点和终点坐标,
//sign[n][2]为连续竹子的的关键坐标(储存在map内)
int other[200002]; //多余不用搜索的竹子
multimap<ll, int> M; //从低到高竹子对应的坐标
multimap<ll, int>::iterator it; //迭代器,用于取出最后一个元素

stack<int> S; //搜索过的竹子
int large; //搜索过的竹子中序号最大的
int small; //搜索过的竹子中序号最小的

/*向右深度优先搜索*/
void dfs1(int n, ll l) { //搜索第n根竹子,长度为l
	n = sign[n][1];
	large = max(large, n); //记录搜索终点
	if (lenth[n + 1] == l) { //向右搜索
		S.push(sign[n + 1][1]); //起点以外搜索过的竹子入栈
		S.push(sign[n + 1][2]); //替代多余的关键坐标
		dfs1(n + 1, l);
	}
}
/*向左深度优先搜索*/
void dfs2(int n, ll l) { //搜索第n根竹子,长度为l
	n = sign[n][0];
	small = min(small, n); //记录搜索起点
	if (lenth[n - 1] == l) { //向左搜索
		S.push(sign[n - 1][0]); //起点以外搜索过的竹子入栈
		S.push(sign[n - 1][2]); //替代多余的关键坐标
		dfs2(n - 1, l);
	}
}
int main() {
	//初始化参数
	for (int i = 0; i <= 200002; i++)
	{
		lenth[i] = 0;
		sign[i][0] = i;
		sign[i][1] = i;
		sign[i][2] = i;
		other[i] = 0;
	}
	//输入总竹子数
	cin >> n;
	//输入竹子高度
	for (int i = 1; i <= n; i++)
	{
		ll L;
		cin >> L;
		lenth[i] = L; //储存在数组
		pair<ll, int> P(L, i); //储存在map容器
		M.insert(P);
	}
	/*循环取出最高竹子*/
	int ans = 0;
	int flag = 0; //循环停止的标志
	while (!flag)
	{
		large = 0;
		small = 200002;
		it = M.end();
		it--;//此时迭代器指向Map最后一个元素
		ll k = (*it).first;
		ll v = (*it).second;//获取键值对
		M.erase(it);//删除当前容器元素
		if (k == 1) {
			flag = 1;
		}
		/*深度优先搜索*/
		if (!flag && other[v] != 1) {
			ans++;//记录搜索次数,即魔法施展次数
			dfs1(v, k);
			dfs2(v, k);
			lenth[v] = floor(sqrt(lenth[v] / 2 + 1));//更新关键竹子高度
			sign[v][0] = small;
			sign[v][1] = large;
			sign[v][2] = v;
			lenth[sign[v][0]] = lenth[v];
			lenth[sign[v][1]] = lenth[v];
			/*出栈操作*/
			while (S.size()) {
				int i = S.top();
				sign[i][0] = small;
				sign[i][1] = large;
				sign[i][2] = v;
				other[i] = 1;
				lenth[i] = lenth[v];
				S.pop();//更新两边竹子的高度,并清除多余的非关键坐标
			}
		}
		/*修改map容器存储*/
		ll nl = floor(sqrt(k / 2 + 1));
		pair<ll, int> P(nl, v);
		M.insert(P);//把新的高度存到Map中
	}
	cout << ans;
	return 0;
}

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

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

相关文章

逆向工程:揭开科技神秘面纱的艺术

在当今这个科技飞速发展的时代&#xff0c;我们每天都在与各种电子产品、软件应用打交道。然而&#xff0c;你是否想过&#xff0c;这些看似复杂的高科技产品是如何被创造出来的&#xff1f;今天&#xff0c;我们就来探讨一下逆向工程这一神秘而又令人着迷的领域。 一、什么是…

Unity 接口、抽象类、具体类对象的配合使用案例

文章目录 示例1&#xff1a;接口&#xff08;Interface&#xff09;示例2&#xff1a;抽象类&#xff08;Abstract Class&#xff09;示例3&#xff1a;结合使用接口与抽象类示例4&#xff1a;多接口实现示例5&#xff1a;抽象类与接口结合 在Unity中使用C#编程时&#xff0c;接…

SSL协议是什么?关于SSL和TLS的常见问题解答

SSL&#xff08;安全套接字层&#xff09;及其后继者TLS&#xff08;传输层安全&#xff09;是用于在联网计算机之间建立经过身份验证和加密的链接的协议。尽管SSL协议在 1999年已经随着TLS 1.0的发布而被弃用&#xff0c;但我们仍将这些相关技术称为“SSL”或“SSL/TLS”。那么…

[C/C++] -- JSON for Modern C++

JSON for Modern C&#xff08;nlohmann/json&#xff09;是一个流行的 C JSON 库&#xff0c;由德国开发者nlohmann编写。这个库提供了简洁而灵活的 API&#xff0c;使得在C中解析和生成JSON数据变得非常方便。 1.JSON简介 JSON&#xff08;JavaScript Object Notation&…

sqli-labs-master靶场训练笔记(54-65|决战紫禁之巓)

2024.2.5 level-54 1、先判断类型和闭合类型 ?id1/0 #正常 证明不是数字型 ?id1 #错误 ?id1 -- a #正常 判断是 闭合 2、 判断列数 这里需要运气&#xff0c;但是根据前面50多关的经验直接猜测是3列 ?id-1 union select 1,2,3 -- a 3、爆表名&#xf…

时序数据库Influxdb查询多个字段_field同一时间的值,组成一条数据

Influxdb将表格数据多个字段_field从垂直列布局聚合成水平布局行字段。 问题 1、Influxdb 是一种时间序列数据库&#xff0c;在我的项目中主要用来存储换热站的测点数据的。换热站有非常多的测点&#xff0c;我们用Flux 语法去查询测点数据&#xff0c;返回的数据结构是每个测…

阿里云增加数据库访问白名单

阿里云增加数据库访问白名单 概况 我们希望在外网访问数据库时&#xff0c;可能会遇到无法连接的问题&#xff0c;这有可能是被拦截了。这时就需要去查看自己的ip有没有在白名单里面&#xff0c;没有的话就把ip加入到白名单。 路径 阿里云控制台-搜索RDS-进入RDS管理控制台…

每日一题——LeetCode1413.逐步求和得到正数的最小值

方法一 个人方法&#xff1a; 找出数组求和过程中出现的最小值&#xff0c;如果这个值最小都>0&#xff0c;那么startValue只需要取最小正数1&#xff0c; 反之startValue取最小值的绝对值1&#xff0c;那么startValuemin一定>1 var minStartValue function(nums) {l…

MTK 多帧算法集成实现流程

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、选择feature和配置feature table二、 挂载算法三、自定义metadata四、APP调用算法五、结语 一、选择feature和配置feature table 1.1 选择feature …

双面板设计的一套经验规则-笔记

过大的分布电感导致信号地干扰也就是地弹(专业名词) 还有就是输出瞬态电流导致的地弹 图中可以看到最高 0.5V 的信号地干扰&#xff0c;这只是单一块开发板的测试结果。如果接上外围电路&#xff0c;甚至面包板电路可以想象噪声水平可能会更高。 双面电路板 经验规则 下面来…

I.MX6u嵌入式linux驱动开发

1&#xff1a;Ubuntu 系统入门 当 Ubuntu 系统入门以后&#xff0c;我们重点要学的就是如何在 Linux 下进行 C 语言开发&#xff0c;如何使 用 gcc 编译器、如何编写 Makefile 文件等等 首先安装虚拟机软件VM&#xff1a; Vmware Workstation 软件可以在 Wmeare …

架构学习(五):scrapy实现自定义代理中间件

scrapy实现自定义代理中间件 前言关卡&#xff1a;实现自定义代理中间件代理中间件源码解析代理池自定义代理中间件 结束 前言 ip检测是比较常规的反爬手段&#xff0c;一般站点会限制ip的访问频率&#xff0c;或者根据ip的访问规律和频率来识别异常访问&#xff0c;从而点对点…

Stable Diffusion 模型下载:majicMIX fantasy 麦橘幻想

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十 下载地址 模型介绍 非常推荐的一个非常绚丽、充满幻想的大模型&#xff0c;由国人“Merjic”发布&#xff0c;下载量颇高。这个模型风格炸裂&#xff0c;远距离脸部需要inpaint以达成…

Leetcode—135. 分发糖果【中等】

2024每日刷题&#xff08;113&#xff09; Leetcode—135. 分发糖果 算法思想 这里可以利用贪心策略&#xff0c;求局部最优解&#xff0c;然后合并为全局最优解。具体来说&#xff0c;将原问题中相邻孩子的条件划分为左相邻孩子和右相邻孩子两个条件&#xff0c;依次求解出两…

NLP中的嵌入和距离度量

本文将深入研究嵌入、矢量数据库和各种距离度量的概念&#xff0c;并提供示例和演示代码。 NLP中的嵌入 嵌入是连续向量空间中对象、单词或实体的数值表示。在NLP中&#xff0c;词嵌入捕获词之间的语义关系&#xff0c;使算法能够更好地理解文本的上下文和含义。 让我们试着用…

Linux操作系统运维-Docker的基础知识梳理总结

Linux操作系统运维-Docker的基础知识梳理总结 docker用来解决不同开发人员软件调试时环境不统一的问题&#xff0c;保证了程序调试时运行环境的一致性。docker的设计理念便是一处镜像&#xff0c;处处运行&#xff0c;即通过产生用户软件&#xff0c;运行环境及其运行配置的统一…

PKI - 01 散列(Hash)函数

文章目录 PKI概述散列日产生活中的指纹的工作原理散列函数的工作原理散列函数的四大特点使用散列函数验证数据的完整性 PKI概述 PKI&#xff08;Public Key Infrastructure&#xff0c;公钥基础设施&#xff09;证书系统是一种用于保护网络通信安全的技术。它基于非对称加密算法…

自己动手打包element UI官方手册文档教程

经常用element ui朋友开发的比较郁闷&#xff0c;官方文档网基本上都是打不开的&#xff0c; 官方&#xff1a;https://element.eleme.io/ 一直打不开&#xff0c;分析下是里面用的cdn链接ssl证书无效。 就想着自己搭建一个element UI文档 自己搭建的&#xff1a; Element文档网…

python 动态显示数据。

界面显示动态的数据。 from time import sleep import serialimport tkinter as tklis[1,10,40] # 打开串行端口 ser serial.Serial(COM3, 9600) # 9600为波特率&#xff0c;根据实际情况进行调整# 创建窗口和画布 window tk.Tk() canvas tk.Canvas(window, width400, heig…

牛客错题整理——C语言(实时更新)

1.以下程序的运行结果是&#xff08;&#xff09; #include <stdio.h> int main() { int sum, pad,pAd; sum pad 5; pAd sum, pAd, pad; printf("%d\n",pAd); }答案为7 由于赋值运算符的优先级高于逗号表达式&#xff0c;因此pAd sum, pAd, pad;等价于(…