当前位置: 首页 > 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.gsyq.cn/news/1582042.html

相关文章:

  • 安达发|揭开照明行业“生产计划排单软件神器”的神秘面纱!
  • 什么是HVV行动(网络攻防演习)?什么是红蓝对抗?(非常详细)零基础入门到精通,收藏这一篇就够了
  • knowhere | 第九课:认证、额度、计费与限流
  • qsort :超级打包工
  • 技术深度解析:1Panel批量操作架构设计与多服务器并行管理实战
  • 外包工日常管理合规指南:从合同到结算,SaaS系统如何嵌入控制点
  • 西门子 CU240E-2 PN 控制单元专业维修服务
  • AI电商工具测评!商品图片AI味太重怎么办?试试这些工具
  • AI写论文工具深度测评:通用大模型与专业工具的真实表
  • [STM32 HAL库][定时器]PWM实验笔记
  • C++ 利用Clock类和Date类定义一个带日期的时钟类ClockWithDate,且对该对象能进行增加秒数的操作
  • 古韵楚风,诗意天成——探寻《诗经》《楚辞》中的绝美名字
  • 微软把 Windows 计算器开源了,3 万 Star 背后藏着什么
  • CocoaHTTPServer:为Apple生态系统构建的嵌入式HTTP服务器框架
  • 快慢指针巧解链表环检测(多解)
  • 2026燕麦奶口碑排行:营养师推荐清单来了
  • 红日靶场二:WebLogic CVE-2019-2725 到域控沦陷全流程
  • 桑坦德银行向全体员工开放AI工具,首季创造3500万欧元价值
  • 别再问 AMD 显卡能不能跑 AI,SGLang 加 TileLang 组合拳给你答案
  • 中小企业怎么做GEO优化?AI时代低成本长效获客指南
  • HIP 算子兼容性排查,AMD 显卡微调中那些奇怪的报错与解法
  • MateClaw v1.6.0 发布:补齐企业 Agent 工程能力,多方面升级助力生产环境
  • 多派生与多继承演示职读类StuTeech
  • AVR单片机内部温度传感器校准指南:从原理到单点/两点校准实践
  • Windows下载教程 Windows 10 保姆级安装步骤(附镜像文件)系统重装图文详解
  • GLM-5.2 vs GPT-5.5 成本实算:每天 1 万/10 万/100 万次请求的账单差距(2026)
  • 掉发和白发同时出现?高仕星维生素b的双重营养方案
  • 零代码组态开发实操:串口屏项目从数月迭代压缩至数天
  • ATtiny20 8位MCU超低功耗设计实战:从架构解析到物联网终端应用
  • 2026实战:用Gemini镜像站解决Spring Boot微服务性能瓶颈与故障排查