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

线段的最少分组

1 - 模型描述

在数轴上,有 \(n\) 条线段,对于第 \(i\) 条线段覆盖的区间为 \([l_i, r_i]\) ,现在你需要对这 \(n\) 条线段按如下的规则进行分组:

  • 同一组的线段之间互不重叠,即对于同一组的线段 \(i, j\) 存在 \(l_j > r_i\)\(r_j < l_i\).

求最少需要分多少组,并输出分组方案。

2 - 结论 & 证明 & 做法

结论:

最小分组等于某点上最大线段覆盖数量。

设最大线段覆盖数量为 \(M\).

证明:

  • 下界:任取一点 \(x\),覆盖 \(x\) 的所有区间两两重叠,必须被分到不同组。因此最少组数 \(\geq\) 覆盖 \(x\) 的线段数。取被覆盖最多的 \(x\),最少组数 \(\geq\) 最大覆盖数 \(M\).
  • 上界:将所有线段按左端点升序排列,维护每一个已建组的 “最大右端点” 集合。
    • 若当前线段的左端点 \(>\) 某一组的最大右端点,则把该线段加入这一组,并更新这一组的最大右端点。
    • 否则为该线段新开一组。
  • 当不得不新开一组时,说明所有已有组的最大右端点都 \(\geq\) 当前线段的左端点 \(l\). 于是:
    • 这些已有组各自的最靠右的线段都覆盖点 \(l\);
    • 加上当前线段也覆盖 \(l\);
    • 所以在点 \(l\) 处至少有(当前分组数 + 1)条线段同时覆盖,覆盖数 \(\geq\) 已建组数 + 1.
  • 推论:在分组过程的 “分组数量” 每增长 1,都能在某个点被覆盖数 “见证”。因此在过程中的任意时刻的分组数量 \(\leq\) 最大覆盖数量 \(M\).
  • 将上下界结合得到,最少组数 = 最大覆盖数量 \(M\).

做法:

  • 思路:按线段左端点 \(l_i\) 升序贪心。维护 “当前已建分组” 的最右端点。
  • 使用小根堆或有序集合维护当前线段是否需要新开一组,同时维护分组方案。
    • 小根堆:\(pair\) 存当前组的最右端点,组号。处理线段 \([l_i, r_i]\) 时:
      • 若堆顶的 \(r < l_i\) 则将此线段加入该组;
      • 否则新开一组。
    • 有序集合:\(pair\) 存当前组的最右端点,组号。每次 lower_bound({l_i, -1}) 找到第一个 \(r \geq l_i\) 的位置,若存在前驱则使用前驱所在组,否则新开一组。
  • 复杂度 \(O(n \cdot logn)\)

3 - 例题 - CSES1164

题目描述:

这里有一家酒店, 和 \(n\) 为即将到达的客人. 每一位客人都需要一间单独的房间。

你知道每位客人的到达日期和离开日期。两位客人只有在第一位到达的客人离开的时间早于第二位客人到达的时间时,才会被分配到同一间房间。

我们最少需要为所有客人总共准备多少房间? 以及如何分配房间?

输入格式:

第一行输入一个整数 \(n\) \((1 \le n \le 2 \cdot 10^5)\): 顾客的数量。

接下来的 \(n\) 行, 每行描述一位顾客。 每一行输入两个整数 \(a\)\(b\) \((1 \le a \le b \le 10^9)\): 到达日期与离开日期。

输出格式:

第一行输出一个整数 \(k\): 最小需要客房数量。

接下来的一行,依次输出为每一位顾客分配的房间号。房间号必须为 \(1,2,\ldots,k\). 你可以输出任意答案。

思路:

  • 将每一位客人的行程想象成线段,左端点为到达日期,右端点为离开日期。
  • 然后使用模型方法解决即可。

参考代码:

#include <bits/stdc++.h>
using namespace std;#define endl '\n'
#define i64 long longstruct Customer{int arrive, leave, number;
};int main() {ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);int n;cin >> n;vector<Customer> cus(n);for (int i = 0; i < n; i ++ ) {cin >> cus[i].arrive >> cus[i].leave;cus[i].number = i;}ranges::sort(cus, [&](auto a, auto b) {return a.arrive < b.arrive;});int cnt = 0;vector<int> ans(n);set<pair<int, int>> leaveTime;for (int i = 0; i < n; i ++ ) {int arrive = cus[i].arrive;int leave = cus[i].leave;int number = cus[i].number;auto it = leaveTime.lower_bound({arrive, -1});if (it == leaveTime.begin()) {ans[number] = ++cnt;leaveTime.insert({leave, cnt});}else {--it;ans[number] = it->second;leaveTime.erase(it);leaveTime.insert({leave, ans[number]});}}cout << cnt << endl;for (int i = 0; i < n; i ++ ) {cout << ans[i] << " \n"[i == n - 1];}
}

4 - 练习

NC201994: https://ac.nowcoder.com/acm/problem/201994

http://www.gsyq.cn/news/81742.html

相关文章:

  • 新房装修不迷路!十大公司深度评测,盛世和家登顶榜首 - 品牌测评鉴赏家
  • GROMACS 2025.4安装(非root用户)
  • 解码string类——字符串处理
  • 新手装修必看!第一次选对装修公司,省心攻略全解析 - 品牌测评鉴赏家
  • windriver 第3章: 安装WinDriver
  • day3 Java基础3
  • windriver 第2章: 了解设备驱动程序
  • 2025年整装公司权威推荐榜:十大特色装修公司满足不同需求 - 速递信息
  • 2025整装公司排名榜!十强家装品牌核心优势对比 - 速递信息
  • 解决IDEA中项目目录的底色变黄
  • 全屋整装公司品牌十强有哪些?2025排名与品牌解析 - 速递信息
  • 第五十九篇
  • 任意地址写basectf_format_string_level1
  • 还在为论文开题报告发愁?7款免费AI工具帮你轻松搞定! - 麟书学长
  • 2025.12.10博客
  • 2025年12月苏州装修公司排名:盛世和家装饰实力解析 - 品牌测评鉴赏家
  • 2025最值得选的AI学习机选购核心:5大品牌实测,看这篇攻略选购不迷茫! - 品牌测评鉴赏家
  • AI 自习室哪家好?2025 年末最新评测:从提分实效到加盟性价比全解析 - 品牌测评鉴赏家
  • CentOS Stream 网络故障排查:静态IP丢失、无法访问的完整解决方案 - 详解
  • 低压相关术语解释
  • TIM定时中断
  • 详细介绍:两台服务器 NFS 共享目录实战
  • 03_DES原理
  • [HNOI2015] 亚瑟王
  • 2025年12月成都小程序开发公司最新推荐,小程序定制开发 电商小程序开发,预订服务小程序开发,活动报名小程序开公司选择指南 - 品牌鉴赏师
  • 多平台批量发布文章的软件哪个好?我选AI智能媒体助理的原因
  • 解决 Chrome 下载 `.crx` 文件被自动删除及“无法安装扩展程序,因为它使用了不受支持的清单版本”难题
  • 不同基础初中生如何选寒假数学网课辅导老师?2025权威指南来了:基础薄弱、中等提升、尖子冲刺全适配 - 速递信息
  • AI 学习机真能提分吗?2025 年首选推荐 科学选购指南 - 品牌测评鉴赏家
  • 优选算法(滑动窗口) - 实践