【二分搜索 C/C++】洛谷 P1873 EKO / 砍树

2025 - 02 - 19 - 第 55 篇
Author: 郑龙浩 / 仟濹(CSND)
【二分搜索】

文章目录

  • 洛谷 P1873 EKO / 砍树
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 输入输出样例 #2
      • 输入 #2
      • 输出 #2
    • 说明/提示
    • 题目中的部分变量
    • 思路
    • 代码

洛谷 P1873 EKO / 砍树

题目描述

伐木工人 Mirko 需要砍 M M M 米长的木材。对 Mirko 来说这是很简单的工作,因为他有一个漂亮的新伐木机,可以如野火一般砍伐森林。不过,Mirko 只被允许砍伐一排树。

Mirko 的伐木机工作流程如下:Mirko 设置一个高度参数 H H H(米),伐木机升起一个巨大的锯片到高度 H H H,并锯掉所有树比 H H H 高的部分(当然,树木不高于 H H H 米的部分保持不变)。Mirko 就得到树木被锯下的部分。例如,如果一排树的高度分别为 20 , 15 , 10 20,15,10 20,15,10 17 17 17,Mirko 把锯片升到 15 15 15 米的高度,切割后树木剩下的高度将是 15 , 15 , 10 15,15,10 15,15,10 15 15 15,而 Mirko 将从第 1 1 1 棵树得到 5 5 5 米,从第 4 4 4 棵树得到 2 2 2 米,共得到 7 7 7 米木材。

Mirko 非常关注生态保护,所以他不会砍掉过多的木材。这也是他尽可能高地设定伐木机锯片的原因。请帮助 Mirko 找到伐木机锯片的最大的整数高度 H H H,使得他能得到的木材至少为 M M M 米。换句话说,如果再升高 1 1 1 米,他将得不到 M M M 米木材。

输入格式

1 1 1 2 2 2 个整数 N N N M M M N N N 表示树木的数量, M M M 表示需要的木材总长度。

2 2 2 N N N 个整数表示每棵树的高度。

输出格式

1 1 1 个整数,表示锯片的最高高度。

输入输出样例 #1

输入 #1

4 7
20 15 10 17

输出 #1

15

输入输出样例 #2

输入 #2

5 20
4 42 40 26 46

输出 #2

36

说明/提示

对于 100 % 100\% 100% 的测试数据, 1 ≤ N ≤ 1 0 6 1\le N\le10^6 1N106 1 ≤ M ≤ 2 × 1 0 9 1\le M\le2\times10^9 1M2×109,树的高度 ≤ 4 × 1 0 5 \le 4\times 10^5 4×105,所有树的高度总和 > M >M >M

题目中的部分变量

tree_num - 树木数量
trees[] - 每个树木的高度
tree_sum - 需要的木材总长度
max_JHight - 锯片的最高高度
max_TreeHight - 树木最高高度
tree_NewSum - 存储当前锯片高度砍的树木高度之和

思路

理一下思路,首先,刚开始是没想到这个题怎么做的,我看到标签写的**“二分算法”**,然后往这方面想才有了思路。

首先,该题要求的是:max_hight锯片的最高高度,这个锯片的高度肯定是有一个区间的,所以只需要在这个区间(1 ~ 最高的树木高度)内查找到一个符合条件的值即可。

即使用二分搜索法在区间 [ 1 —— max_TreeHight ] 内寻找符合**条件(下面写了什么条件)**的值(或叫高度)

这个所谓条件就是:

锯下来的所有木材之和 大于等于 需要的木材总长度

注意数据范围

1≤N≤106,1≤M≤2×109,树的高度 ≤4×105,所有树的高度总和 >M

所以 long long

还有一些细节问题

关于一些特殊情况以及细节,我已经在写代码的时候进行了标注和注释

既然理清思路,就开始写代码了,代码如下

代码

//洛谷P1873 KEO/砍树
// 2025-02-18
// 郑龙浩 / 仟濹(CSDN)
// tree_num - 树木数量
// trees[] - 每个树木的高度
// tree_sum - 需要的木材总长度
// max_JHight - 锯片的最高高度
// max_TreeHight - 树木最高高度
// tree_NewSum - 存储当前锯片高度砍的树木高度之和
#include <iostream>
#include <algorithm>
using namespace std;
// 二分搜索符合 锯下来的所有木材之和 **大于等于** 需要的木材总长度 的高度
long long binary_searchSelf( long long trees[], long long tree_num, long long tree_sum, long long max_TreeHight ){
    long long left = 0, right = max_TreeHight, middle; // 左定位 右定位 中间定位
    long long tree_NewSum; // 存储当前锯片高度砍的树木高度之和
    long long max_JHight = 0;
    // 寻找最合适高度(锯片的)

    // 因为这个地方写为 left < right 我找错找了好久,要注意
    // 千万不要写成 left < right
    // 为什么left == right 的时候仍然要进入循环呢,因为此时的left 与 right还未曾参与计算
    // 需要进入循环将 middle 赋值为 (left + right) / 2
    while( left <= right ){
        tree_NewSum = 0;
        middle = (left + right) / 2;
        for( int i = 0; i < tree_num; i ++ ){
            // 如果电锯高度保持在 树木的高度内,锯下来就是>0,累加;电锯高度大于树木高度,则是砍空气,不计数(算出来是负数)
            // 即:如果可砍,则就累加
            if( middle < trees[ i ] )
                tree_NewSum += trees[ i ] - middle;
        }
        // 不断寻找 当前锯片高度砍的树木高度之和 == 需要的木材总长度 的数值
        // 招不到就找 当前锯片高度砍的树木高度之和 > 需要的木材总长度 且 最接近的 数值
        if( tree_NewSum >= tree_sum ){
            // 当前锯下来的总和 >= 需要的木材总和
            max_JHight = middle;
            left = middle + 1;
        } else{
        // 当前锯下来的总和 < 需要的木材总和
        // 至于为什么在这不 max_JHight = middle 操作,是因为锯下来的总和不满足需要的木材
            right = middle - 1;
        }
    }
    return max_JHight; // 返回锯片最高高度
}
int main( void ){
    long long tree_num, tree_sum; //  树木数量 需要的木材总长度
    cin >> tree_num >> tree_sum; //  输入 木数量 需要的木材总长度
    long long trees[ tree_num ]; //  每个树木的高度
    long long max_TreeHight; //  树木最高高度
    for( int i = 0; i < tree_num; i ++ ){
        cin >> trees[ i ];
    }
    sort( trees, trees + tree_num ); // 让数据变为升序,以便使用 二分搜索法
    max_TreeHight = trees[tree_num - 1];
    cout << binary_searchSelf(trees, tree_num, tree_sum, max_TreeHight) << endl;
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

unity学习49:寻路网格链接 offMeshLinks, 以及传送门效果

目录 1 网格链接 offMeshLinks 功能入口 1.1 unity 2022之前 1.2 unity 2022之后 2 网格链接 offMeshLinks 功能设置 3 点击 offMeshLinks 功能里的bake 3.1 unity 2022之前 3.2 unity 2022之后 3.3 实测link 3.4 跳跃距离增大&#xff0c;可以实现轻功类的效果 4 …

HarmonyOS NEXT网络状态监听HTTP和RCP请求网络

当我们在HarmonyOS NEXT中开发的应用&#xff0c;基本上都会使用网络请求&#xff0c;从服务端获取数据在客户端显示或者供用户交互&#xff0c;有时候网络发生变化时&#xff0c;我们需要做一些相应的操作&#xff0c;接下来我们一起来了解下在HarmonyOS NEXT下如何监听网络状…

如何在 VS Code 中快速使用 Copilot 来辅助开发

在日常开发中&#xff0c;编写代码往往是最耗时的环节之一。而 GitHub Copilot&#xff0c;作为一款 AI 编码助手&#xff0c;可以帮助开发者 自动补全代码、生成代码片段&#xff0c;甚至直接编写完整的函数&#xff0c;大幅提升编码效率。那么&#xff0c;如何在 VS Code 中快…

【16届蓝桥杯寒假刷题营】第2期DAY1I

4.有向无环的路径数 - 蓝桥云课 问题描述 给定 N 个节点 M 条边的有向无环图&#xff0c;请你求解有多少条 1 到 N 的路径。 由于答案可能很大&#xff0c;你只需要输出答案对 998244353 取模后的结果。 输入格式 第一行包含 2 个正整数 N,M&#xff0c;表示有向无环图的节…

伯克利 CS61A 课堂笔记 10 —— Trees

本系列为加州伯克利大学著名 Python 基础课程 CS61A 的课堂笔记整理&#xff0c;全英文内容&#xff0c;文末附词汇解释。 目录 01 Trees 树 Ⅰ Tree Abstraction Ⅱ Implementing the Tree Abstraction 02 Tree Processing 建树过程 Ⅰ Fibonacci tree Ⅱ Tree Process…

Spring Boot 定时任务:轻松实现任务自动化

在现代应用开发中&#xff0c;定时任务是一个常见的需求。比如&#xff0c;我们可能需要定时清理过期数据、定时发送邮件通知等。 操作流程 开启定时任务注解 在启动类添加注解EnableScheduling 设置时间&#xff08;固定时间间隔&#xff09; 使用 Scheduled 注解创建定时…

通过监督微调提升多语言大语言模型性能

引言 澳鹏助力一家全球科技公司提升其大语言模型&#xff08;LLM&#xff09;的性能。通过提供结构化的人工反馈形式的大语言模型训练数据&#xff0c;让该模型在30多种语言、70多种方言中的表现得到优化。众包人员们进行多轮对话&#xff0c;并依据回复的相关性、连贯性、准确…

Flask实现高效日志记录模块

目录 一. 简介&#xff1a; 1. 为什么需要请求日志 二. 日志模块组成 1. 对应日志表创建&#xff08;包含日志记录的关键字段&#xff09; 2. 编写日志记录静态方法 3. 在Flask中捕获请求日志 4. 捕获异常并记录错误日志 5. 编写日志接口数据展示 6. 写入数据展…

【学习笔记】Cadence电子设计全流程(一)Cadence 生态及相关概念

【学习笔记】Cadence电子设计全流程&#xff08;一&#xff09;Cadence 生态及相关概念 1.1 Cadence 生态系统及各模块关系1.2 Cadence相较于Altium Designer在硬件设计中的优势 1.1 Cadence 生态系统及各模块关系 Cadence 提供了一套完整的电子设计自动化 (EDA) 工具链&#…

【Linux Redis】关于用docker拉取Redis后,让虚拟机运行起来redis,并使得其可以连接到虚拟机外的navicat。

步骤一&#xff1a;拉取Redis镜像 docker pull redis 这个命令会下载最新版本的Redis镜像到你的本地Docker仓库中。你也可以指定一个具体的版本号&#xff0c;例如docker pull redis:6.2.6&#xff0c;来拉取特定版本的Redis镜像。 如果拉取遇到问题请参考【Linux AnolisOS】关…

蓝桥与力扣刷题(蓝桥 裁纸刀)

本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 题目&#xff1a;小蓝有一个裁纸刀&#xff0c;每次可以将一张纸沿一条直线裁成两半。 小蓝用一张纸打印出两行三列共 6 个二维码&#xff0c;至少使用九次裁出来&#xff0c…

pdf转换成word在线 简单好用 支持批量转换 效率高 100%还原

pdf转换成word在线 简单好用 支持批量转换 效率高 100%还原 在数字化办公的浪潮中&#xff0c;文档格式转换常常让人头疼不已&#xff0c;尤其是 PDF 转 Word 的需求极为常见。PDF 格式虽然方便阅读和传输&#xff0c;但难以编辑&#xff0c;而 Word 格式却能灵活地进行内容修…

Django ModelForm使用(初学)

1.目的是根据员工表字段&#xff0c;实现一个新增员工的数据填写页面 2.在views.py文件中按下面的格式写 定义 ModelForm 类&#xff1a;UserModelForm &#xff08;自己命名的类名&#xff09;使用时需要导入包 定义视图函数&#xff1a;user_model_form_add&#xff08;在函…

基于大牛直播SDK的Android平台低延迟RTSP|RTMP播放与录像技术实践

技术背景 随着直播、安防监控、远程会议等场景对实时性与稳定性要求的提升&#xff0c;低延迟流媒体播放与录像成为核心技术需求。大牛直播SDK的SmartPlayer模块提供了完整的解决方案&#xff0c;支持RTSP、RTMP协议的多实例播放、硬件解码、实时快照、录像管理等功能&#xf…

小怿学习日记(七) | Unreal引擎灯光架构

灯光的布局对于HMI场景中车模的展示效果有着举足轻重的地位。本篇内容将简单介绍ES3.1的相关知识&#xff0c;再深入了解Unreal引擎中车模的灯光以及灯光架构。 一、关于ES3.1 1.1 什么是ES3.1 ES3.1这个概念对于美术的同学可能比较陌生&#xff0c;ES3.1指的是OpenGL ES3.1&…

DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入)

前言 在当今数字化时代&#xff0c;AI编程助手已成为提升开发效率的利器。DeepSeek作为一款强大的AI模型&#xff0c;凭借其出色的性能和开源免费的优势&#xff0c;成为许多开发者的首选。今天&#xff0c;就让我们一起探索如何将DeepSeek接入PyCharm&#xff0c;实现高效、智…

广度优先搜索详解--BFS--蒟蒻的学习之路

1.什么是广度优先搜索? 广度优先搜索&#xff08;Breadth-First Search&#xff0c;简称BFS&#xff09;是一种遍历或搜索树和图的算法&#xff0c;也称为宽度优先搜索&#xff0c;BFS算法从图的某个节点开始&#xff0c;依次对其所有相邻节点进行探索和遍历&#xff0c;然后再…

. Unable to find a @SpringBootConfiguration(默认软件包中的 Spring Boot 应用程序)

解决&#xff1a; 新建一个包即可 问题&#xff1a; 默认软件包中的 Spring Boot 应用程序。 原因&#xff1a; 默认包的定义 &#xff1a; 如果一个 Java 类没有使用 package 声明包名&#xff0c;则该类会被放置在默认包中。Spring Boot 遵循 Java 的包管理约定&#xff…

DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地

对于个人开发者或尝鲜者而言&#xff0c;本地想要部署 DeepSeek 有很多种方案&#xff0c;但是一旦涉及到企业级部署&#xff0c;则步骤将会繁琐很多。 比如我们的第一步就需要先根据实际业务场景评估出我们到底需要部署什么规格的模型&#xff0c;以及我们所要部署的模型&…

“三次握手”与“四次挥手”:TCP传输控制协议连接过程

目录 什么是TCP协议 “三次握手”建立连接 “四次挥手”断开连接 “三次握手”和“四次挥手”的反思 总结 什么是TCP协议 想象一下&#xff0c;你和远方的朋友要进行一场电话交流&#xff0c;但这通电话不仅仅是随便聊聊&#xff0c;而是要传递一封重要的信件。为了确保这…