当前位置: 首页 > news >正文

题解:洛谷 AT_abc463_d [ABC463D] Maximize the Gap

本文分享的必刷题目是从蓝桥云课洛谷AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。

欢迎大家订阅我的专栏:算法题解:C++与Python实现!

附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总


【题目来源】

洛谷:AT_abc463_d [ABC463D] Maximize the Gap - 洛谷

【题目描述】

There areN NNcloths on a number line. Thei ii-th( 1 ≤ i ≤ N ) (1\le i\le N)(1iN)cloth covers the interval[ L i , R i ] \lbrack L _ i,R _ i\rbrack[Li,Ri]on the line. A point on the line may be covered by two or more cloths, or not covered by any cloth.

Two cloths are said to overlap if some point on the line is covered by both of those cloths.

For two cloths that do not overlap, define theirdistanceas follows:

  • The minimum value of∣ p − q ∣ |p-q|pqover all pointsp ppcovered by one cloth and all pointsq qqcovered by the other cloth.

ForK KKcloths no two of which overlap, define theirscoreas the minimum distance among all pairs of those cloths. Find the maximum possible score when choosingK KKcloths from theN NNcloths so that no two of the chosen cloths overlap.

If it is impossible to chooseK KKsuch cloths, output-1.

数轴上有N NN块布。第i ii( 1 ≤ i ≤ N ) (1\le i\le N)(1iN)布覆盖数轴上的区间[ L i , R i ] [L_i, R_i][Li,Ri]。数轴上的一个点可能被两块或更多块布覆盖,也可能不被任何布覆盖。

如果数轴上的某个点被两块布同时覆盖,则称这两块布重叠。

对于两块不重叠的布,定义它们之间的距离如下:

  • 一块布覆盖的所有点p pp与另一块布覆盖的所有点q qq之间,∣ p − q ∣ |p-q|pq的最小值。

对于K KK块两两之间都不重叠的布,定义它们的得分为这些布中所有两两组合之间的距离的最小值。请从N NN块布中选出K KK块两两不重叠的布,使得得分最大。

如果无法选出这样的K KK块布,输出-1

【输入】

The input is given from Standard Input in the following format:

N NNK KK
L 1 L _ 1L1R 1 R _ 1R1
L 2 L _ 2L2R 2 R _ 2R2
⋮ \vdots
L N L _ NLNR N R _ NRN

【输出】

Output the answer.

【输入样例】

6 3 1 12 2 7 5 9 9 13 10 18 15 20

【输出样例】

2

【核心思想】

  1. 问题分析:给定N NN块布,每块覆盖区间[ L i , R i ] [L_i, R_i][Li,Ri]。需要选出K KK块两两不重叠的布,使得所有选中布之间两两距离的最小值最大化。两块不重叠布的距离定义为它们覆盖点之间∣ p − q ∣ |p-q|pq的最小值,即若布i ii在布j jj左侧且不重叠,则距离为L j − R i L_j - R_iLjRi。这是一个二分答案 + 贪心判定问题。

  2. 算法选择

    • 二分答案(Binary Search):对最大可能的得分进行二分,将最优化问题转化为判定问题
    • 贪心策略(Greedy):按右端点升序排序后,每次优先选择结束最早的布,确保留给后续布尽可能多的空间
    • 关键性质:按右端点排序后,若所有相邻选中布之间的距离≥ m i d \geq midmid,则任意两块选中布之间的距离都≥ m i d \geq midmid。因为对于i < j < k i < j < ki<j<kd i s t ( i , k ) = L k − R i = ( L k − R j ) + ( R j − R i ) ≥ d i s t ( j , k ) ≥ m i d dist(i,k) = L_k - R_i = (L_k - R_j) + (R_j - R_i) \geq dist(j,k) \geq middist(i,k)=LkRi=(LkRj)+(RjRi)dist(j,k)mid
  3. 关键步骤

    • 初始化:读取N NN(布的总数)、K KK(需要选出的数量)
    • 存储区间:读取每块布的[ L i , R i ] [L_i, R_i][Li,Ri],存入数组a [ 1.. N ] a[1..N]a[1..N]
    • 按右端点排序sort(a+1, a+n+1, cmp),按R i R_iRi升序排列
    • 二分答案
      • 范围[ 0 , 10 9 ] [0, 10^9][0,109],取上中点mid = (l + r + 1) / 2防止死循环
      • check(mid)为真,说明得分≥ m i d \geq midmid可行,l = mid
      • 否则r = mid - 1
    • 判定函数check(mid)(贪心选择):
      • 初始化cnt = 1last = a[1].r(先选右端点最小的布)
      • 遍历i ii2 22N NN
        • a [ i ] . l − l a s t ≥ m i d a[i].l - last \geq mida[i].llastmid(当前布与上一块选中布的距离足够):
          • cnt++,选中当前布
          • last = a[i].r,更新最后选中布的右端点
          • cnt >= k,返回true
      • 返回cnt >= k
    • 输出答案:若最终l = 0 l = 0l=0,输出-1(无法选出K KK块);否则输出l ll
  4. 时间/空间复杂度

    • 时间复杂度:O ( N log ⁡ N + N log ⁡ M A X ) O(N \log N + N \log MAX)O(NlogN+NlogMAX),排序O ( N log ⁡ N ) O(N \log N)O(NlogN),二分O ( log ⁡ M A X ) O(\log MAX)O(logMAX),每次判定O ( N ) O(N)O(N)
    • 空间复杂度:O ( N ) O(N)O(N),存储区间数组
  5. 二分答案 + 贪心判定的核心思想

    • 最优化转判定:将"最大化最小距离"转化为"判断是否可以选择K KK块布使得最小距离≥ m i d \geq midmid"
    • 贪心选择策略:按右端点排序后优先选择结束早的区间,为后续选择预留最大空间,这是区间调度问题的经典贪心策略
    • 关键性质转化:通过排序保证非相邻区间的距离一定不小于相邻区间的距离,从而只需判定相邻区间距离
    • 上中点取整:使用(l + r + 1) / 2取上中点,配合l = mid/r = mid - 1避免死循环
    • 适用于"最大化最小值"或"最小化最大值"类区间选择问题

【算法标签】

#普及 #整数二分

【代码详解】

#include<bits/stdc++.h>usingnamespacestd;constintN=200005;// 最大布的数量intn,k;// n: 布的总数, k: 需要选出的布的数量structNode{intl,r;// l: 区间左端点, r: 区间右端点}a[N];// 存储所有布的区间信息// 按右端点升序排序(贪心策略:优先选择结束早的区间)boolcmp(Node x,Node y){returnx.r<y.r;}// 检查:是否能选出至少 k 块布,使得任意两块相邻选中的布之间的距离 >= midboolcheck(intmid){intcnt=1;// 已选中的布的数量,默认先选第一块(右端点最小的)intlast=a[1].r;// 上一次选中的布的右端点for(inti=2;i<=n;i++){// 当前布的左端点与上一次选中的布的右端点的距离 >= mid// 即两块布不重叠且距离至少为 midif(a[i].l-last>=mid){cnt++;// 选中当前布last=a[i].r;// 更新 last 为当前布的右端点if(cnt>=k)// 已选出 k 块布,满足条件returntrue;}}returncnt>=k;// 判断最终是否选出了至少 k 块布}intmain(){cin>>n>>k;// 读入布的总数和需要选出的数量for(inti=1;i<=n;i++)cin>>a[i].l>>a[i].r;// 读入每块布的区间sort(a+1,a+n+1,cmp);// 按右端点升序排序// 二分查找最大可能的得分intl=0,r=1e9;// 答案范围:[0, 1e9]while(l<r){intmid=(l+r+1)/2;// 取上中点,防止死循环if(check(mid))l=mid;// mid 可行,尝试更大的得分elser=mid-1;// mid 不可行,缩小范围}if(l==0)// 如果最大得分仍为0,说明无法选出 k 块不重叠的布cout<<-1<<endl;elsecout<<l<<endl;// 输出最大可能的得分return0;}

【运行结果】

6 3 1 12 2 7 5 9 9 13 10 18 15 20 2
http://www.jsqmd.com/news/1070097/

相关文章:

  • tvm cuda后端编译路径
  • iNeuOS_Doctor,一款基于人工智能在医疗领域的病情咨询及医学影像分析平台,例如CT\X光片\病理成像\诊断病历等 项目介绍
  • 从驱动到服务,DevCloud 上 ROCm 7.x 全链路部署复盘
  • 【OpenClaw】一台 Windows 主机部署双 Gateway:两个微信 + 一台主机 + 模型隔离完整踩坑实录
  • Harness 教程 08:日志查看与故障排查:Execution History、Step Log、Delegate 日志与 Kubernetes 事件定位:国内网络环境落地版
  • 一条产线该不该上机器人——给集成商/工程师的决策框架与算账逻辑
  • 亮相国际应急顶级平台|百分点科技发布应急救援智能体ResQ-AI
  • VRTK v4农场示例:基于Tilia架构的现代VR开发实践
  • 判断闰年日期
  • 什么是HVV行动(网络攻防演习)?什么是红蓝对抗?(非常详细)零基础入门到精通,收藏这一篇就够了
  • 解析编程语言的新范式:Tree-sitter 如何重塑代码分析工具
  • Claude Code 安装与配置教程
  • 安达发|揭开照明行业“生产计划排单软件神器”的神秘面纱!
  • 第七:PC端自动化测试实战教程-pywinauto等待方法大集合
  • 2026年AI应用找工作,简历写了等于没写的那几个坑
  • Markwhen深度解析:从文本到时间线的技术突破与实践指南
  • Testify:Go 测试这件事,它帮你省掉一半代码
  • knowhere | 第九课:认证、额度、计费与限流
  • qsort :超级打包工
  • python psycopg2库 操作postgresql
  • ByteArrayInputStream和DataInputStream的源码分析和使用方法详细分析前言)UTF-8 编码规则合集 - 【Java—JDK源码】IO的使用和IO相关的源码(14)1
  • 【硬核拆解】飞利浦 THE TINA (TAV9000F/93) 评测:复古外壳下的现代嵌入式系统逻辑
  • Spree Commerce:开源无头电商平台,B2B 和跨境都能用
  • AI价值:理性评估三维度
  • 3步构建AI投研框架:用Serenity-skill提升你的投资研究效率
  • 技术深度解析:1Panel批量操作架构设计与多服务器并行管理实战
  • Neural Amp Modeler终极指南:从零开始打造专业级吉他音箱模拟
  • AGI时代,万物趋于免费,真正稀缺的只剩这5样东西
  • AI写论文工具深度测评:通用大模型与专业工具的真实表
  • 浏览器AI助手终极指南:5分钟搭建本地智能浏览体验