管道(acwing,蓝桥杯,二分)

题目描述:

有一根长度为 len 的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。

一开始管道是空的,位于 Li的阀门会在 Si 时刻打开,并不断让水流入管道。

对于位于 Li的阀门,它流入的水在 Ti(Ti≥Si)时刻会使得从第 Li−(Ti−Si) 段到第 Li+(Ti−Si)段的传感器检测到水流。

求管道中每一段中间的传感器都检测到有水流的最早时间。

输入格式:

输入的第一行包含两个整数 n,len,用一个空格分隔,分别表示会打开的阀门数和管道长度。

接下来 n行每行包含两个整数 Li,Si,用一个空格分隔,表示位于第 Li 段管道中央的阀门会在 Si 时刻打开。

输出格式:

输出一行包含一个整数表示答案。

数据范围:

对于 30%的评测用例,n≤200,Si,len≤3000;
对于 70%的评测用例,n≤5000,Si,len≤1e5;
对于所有评测用例,1≤n≤1e5,1≤Si,len≤1e9,1≤Li≤len,Li−1<Li。

输入样例:

3 10
1 1
6 5
10 2

输出样例:

5

分析步骤:

  第一:我们拿到这道题我们可以看到,是一段管道里有许多的水龙头,当开启不同水龙头的时候它可以向两边扩散速度是:1段/s。不同水龙头控制的区域也不一样,至此我们分析出了第一个特点有区间问题,需要合并看看有没有全部覆盖管道

            我们还可以发现当时间开的越长,管道内有水的区域也越长,这呈现一种单调的特点,并且我们可以求出一个时间点,在这个时间点的左边管道内不能全部都流过水,在这个时间点和以后都可以覆盖全管道。至此也满足了二分的特点

            所以本题要运用二分+区间合并来做;

 

第二:知道了考的知识点,咱们就要书写主函数,把握整体框架。

           首先把值都输入进去,其次开始二分

            定义我们的左节点 l 为 0 因为有可能水管从第零分钟就一直开着,并且每个管道段落都有水龙头,所以最小时间可能是 0

             定义右节点 r 为 2e9 .因为题目说了 Si 最大为 1e9  所以有可能在最后一秒也就是1e9秒时 ,开启开关并且只有一个开关且在第一个管道之内,所以要覆盖管道又要1e9s 所以两个 1e9 相加就是 2e9。

           求出mid,再判断一下这个 mid 的值

            如果是对的,则证明比 mid 的时间大小更大的值就更可以覆盖满管道.因为假如 mid 为5秒时已经覆盖了管道,那么6秒更会是管道内充水。所以应该将 mid 赋值给 r

            如果 mid 的时间大小不可以,那么比mid还小的话更是不可能覆盖的了管道了。所以应该将 mid + 1 的值 赋值给 l;

int main()
{
    cin>>n>>m;
    for(int i = 0 ; i < n ; i ++){
        cin>>q[i].x>>q[i].y;
    }
    LL l = 0 , r = 2e9;
    while(l<r){
        LL mid = (l+r) / 2;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }
    cout<<r;
    return 0;
}

  第三:书写 check 函数定义一个 计数器 cnt 用一个f or 循环将之前存储的数据取出来,如果mid这个时间大于了我们的S这个时间的话,那么就意味着这个开关已经开启了并且流出了一段的水,这段时间的差值 就是这个开关向左右两边扩散的距离,所以我们用 t 计算出这段时间差。

          确定左右区间:

           我们接下来看这个开关可以控制的区间范围因为 t 就是扩散的距离 所以我们的 int l = max(1, L-t ) ,左边界范围就是第 L 个开关向左走了 t 时间的路 和 1 取最大值进行动态更新

            r = min((LL)m,(LL)L+t);右边界范围就是第 L 个开关向左走了 t 时间的路 和 m 取最小值进行动态更新因为不可以超过管道长度。

            最后将这个开关的区间边界放入 p 数组之中;至此我们区间范围已然确定。

int cnt = 0 ; 
     for(int i = 0 ; i < n ; i ++){
         int L = q[i].x , S = q[i].y;
         if(mid >= S){
             int t = mid - S;
             int l = max(1,L-t) , r = min((LL)m,(LL)L+t);
                  p[cnt++]={l,r};
         }
     }

  第四:接下来进行区间合并。我们先进行sort排序这样这些区间的左端点就可以从小到大排序,我们就只要比较右端点就行。

           我们定义左端点 st 为 -1 ; 右端点ed 为 -1 

           如果 我们的左端点st <= 上一个存值的区间右端点 加 1 的话我们就只需要更新一下我们右节点 ed 就可以把两个区间合并了。为什么要加1?直接小于等于 ed 不行吗? 不可以 。因为ed那里已经有水了,只是 ed+1 的那个点没有水,所以如果我们的 l == ed+1的话也是可以算连接上了的。

          如果 我们的左端点st > 上一个存值的区间右端点 加 1 的话 就证明这两个区间必有间隙则更改我们的st 和 ed为新的区间端点。

         最终返回判断一下st是否为 1 并且 ed是否为管道长度。如果都符合就返回true,有一个不符合就是false;

            


     sort(p,p+cnt);
     int ed = -1 , st = -1;
     for(int i = 0 ; i < cnt ; i ++){
        if(p[i].x <= ed + 1 ) ed = max(ed , p[i].y);
        else st = p[i].x , ed = p[i].y;
     }
    return st == 1 and ed == m;

  

注意:区间合并就三种情况相交里包含两种,还有一种相离

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#define x first
#define y second

using namespace std;

const int N = 1e5+10;
typedef long long LL;
typedef pair<int, int> PII;
PII q[N], p[N];
LL n,m;

bool check(int mid){
     int cnt = 0 ; 
     for(int i = 0 ; i < n ; i ++){
         int L = q[i].x , S = q[i].y;
         if(mid >= S){
             int t = mid - S;
             int l = max(1,L-t) , r = min((LL)m,(LL)L+t);
                  p[cnt++]={l,r};
         }
     }
     sort(p,p+cnt);
     int ed = -1 , st = -1;
     for(int i = 0 ; i < cnt ; i ++){
        if(p[i].x <= ed + 1 ) ed = max(ed , p[i].y);
        else st = p[i].x , ed = p[i].y;
     }
    return st == 1 and ed == m;
}

int main()
{
    cin>>n>>m;
    for(int i = 0 ; i < n ; i ++){
        cin>>q[i].x>>q[i].y;
    }
    LL l = 0 , r = 2e9;
    while(l<r){
        LL mid = (l+r) / 2;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }
    cout<<r;
    return 0;
}

 

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

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

相关文章

WRF模型运行教程(ububtu系统)--III.运行WRF模型(官网案例)

零、创建DATA目录 # 1.创建一个DATA目录用于存放数据&#xff08;一般为fnl数据&#xff0c;放在Build_WRF目录下&#xff09;。 mkdir DATA # 2.进入 DATA cd DATA 一、WPS预处理 在模拟之前先确定模拟域&#xff08;即模拟范围&#xff09;,并进行数据预处理&#xff08…

我的尝试:Codigger + Vim

若您愿意耐心投入&#xff0c;学习 Vim 的过程其实远比想象中轻松。我对 Vim 产生兴趣&#xff0c;主要是源于它对提升生产力的巨大潜力。我尝试了 Neovim、NvChad 以及 Codigger Vim 插件&#xff0c;如今我的工作效率已远超从前。 那么&#xff0c;Vim 究竟是什么呢&#xff…

Leetcode 79. 单词搜索

心路历程&#xff1a; 做完这道题才发现是回溯&#xff0c;一开始想的是递归&#xff0c;判断完第i个字符后&#xff0c;只需要挨个判断第i1个字符在不在第i个字符的邻域。后来发现由于不能重复使用元素&#xff0c;所以需要维护一个visited列表&#xff0c;并且在遍历所有可能…

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——自适应大邻域算法(ALNS)

基于python语言&#xff0c;采用经典自适应大邻域算法&#xff08;ALNS&#xff09;对 需求拆分车辆路径规划问题&#xff08;SDVRP&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整3. 求解结果4. 代码片段参考 往期优质资源 经过一年多的创作&#xff0c;目前…

Aigtek超声功率放大器产品介绍

超声功率放大器是一种特殊类型的功率放大器&#xff0c;专门用于增强和放大超声信号的功率。它在医疗、工业和科学领域中得到广泛应用。 一、超声功率放大器的基本概述 超声功率放大器是一种能够将低功率超声信号放大到更高功率水平的设备。它是超声系统的关键组成部分&#xf…

力扣1. 两数之和

思路&#xff1a;用一个map存放 已遍历过的元素和下标&#xff1b; 若当前元素是nums[i], 且该元素的另一半 target-nums[i] 在已遍历过的map里面&#xff0c;则返回两个元素的下标&#xff1b; class Solution {public int[] twoSum(int[] nums, int target) {int[] ans new…

腾讯云服务器多少钱1个月?2024一个月收费阿济格IE吧

2024腾讯云服务器多少钱一个月&#xff1f;5元1个月起&#xff0c;腾讯云轻量服务器4核16G12M带宽32元1个月、96元3个月&#xff0c;8核32G22M配置115元一个月、345元3个月&#xff0c;腾讯云轻量应用服务器61元一年折合5元一个月、4核8G12M配置646元15个月、2核4G5M服务器165元…

数据结构:详解【顺序表】的实现

1. 顺序表的定义 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。动态顺序表与数组的本质区别是——根据需要动态的开辟空间大小。 2. 顺序表的功能 动态顺序表的功能一般有如下几个&#xff1a; 初始化顺序表打印顺序…

PlantUML Integration 编写短信服务类图

PlantUML Integration 写一个类图&#xff0c;主要功能为 1、编写一个serviceSms短信服务类&#xff1b; 2、需要用到短信的地方统一调用基建层的服务即可&#xff1b; 3、可以随意切换、增加短信厂商&#xff0c;不需要更改场景代码&#xff0c;只需要更改application.yml 里面…

Redis数据结构对象中的对象共享、对象的空转时长

对象共享 概述 除了用于实现引用计数内存回收机制之外&#xff0c;对象的引用计数属性还带有对象共享的作用。 在Redis中&#xff0c;让多个键共享同一个值对象需要执行以下两个步骤: 1.将数据库键的值指针指向一个现有的值对象2.将被共享的值对象的引用计数增一 目前来说…

【Godot4.2】2D导航01 - AStar2D及其使用方法

概述 对于2D平台跳跃或飞机大战&#xff0c;以及一些直接用键盘方向键操控玩家的游戏&#xff0c;是根本用不到寻路的&#xff0c;因为只需要检测碰撞就可以了。 但是对于像RTS或战棋这样需要操控玩家到地图指定位置的移动方式&#xff0c;就绝对绕不开寻路了。 导航、碰撞与…

微信小程序接口请求出错:request:fail url not in domain list:xxxxx

一、微信小程序后台和开发者工具配的不一样导致了这个错误 先说结论&#xff1a; 开发者工具配置了https://www.xxx.cn/prod-api/ 微信后台配置了 https://www.xxx.cn 一、最开始 开发者工具配置了https://www.xxx.cn:7500 微信后台配置了 https://www.xxx.cn 报错:reques…

代码随想录算法训练营第53天 | 1143.最长公共子序列 ,1035.不相交的线 ,53. 最大子序和

动态规划章节理论基础&#xff1a; https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 1143.最长公共子序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-common-subsequence/description/ 思路&…

ASP .Net Core ILogger日志服务

&#x1f433;简介 ILogger日志服务是.NET平台中的一个内置服务&#xff0c;主要用于应用程序的日志记录。它提供了灵活的日志记录机制&#xff0c;允许开发者在应用程序中轻松地添加日志功能。以下是其主要特点和组件&#xff1a; ILogger接口&#xff1a;这是ILogger日志服…

电脑数据安全新利器:自动备份文件的重要性与实用方案

一、数据安全的守护神&#xff1a;自动备份文件的重要性 在数字化时代&#xff0c;电脑中的文件承载着我们的工作成果、个人回忆以及众多重要信息。然而&#xff0c;数据丢失的风险无处不在&#xff0c;无论是硬件故障、软件崩溃&#xff0c;还是恶意软件的攻击&#xff0c;都…

JupytetNotebook常用的快捷键

Jupyter Notebook 中常用的快捷键&#xff1a; 切换到命令模式&#xff1a;按 Esc 键。切换到编辑模式&#xff1a;按 Enter 键。运行当前单元格并选择下面的单元格&#xff1a;按 Shift Enter。运行当前单元格并插入新的单元格在下面&#xff1a;按 Alt Enter。删除当前单元…

【Vue3】Vue3中的编程式路由导航 重点!!!

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

test测试类-变量学习

test测试类 作用&#xff1a;标记到类上成为测试类&#xff0c;标记到方法上成为测试方法 变量&#xff1a;测试类的变量&#xff0c;在测试类括号中应用 1、invocationCount变量 意思是这个方法应该被调用的次数。 在测试框架中&#xff0c;特别是当使用参数化测试或数据驱动…

HarmonyOS(鸿蒙)快速入门

一:下载开发工具 鸿蒙的开发工具叫DevEco 下载点击 其他部分都一直next 就行,这个页面出现的install 建议都点击install 然后单独选择安装目录 可能存在的问题 就是之前安装nodejs&#xff08;比如自己开发web或者RN等情况&#xff09;版本低 等情况 所以建议你单独安装一次 …

Avalon总线学习

Avalon总线学习 avalon总线可以分为&#xff1a; Avalon clock interface Avalon reset interface Avalon Memory mapped interface Avalon iterrupt interface Avalon streaming interface Avalon tri-state conduit interface Avalon conduit interface 1、Avalon c…
最新文章