1 条题解
-
0
题目重述(便于理解)
有 条线段 。
一个线段集合称为复杂集合,如果它可以划分成若干个子集,使得:
- 所有子集的大小相同,设为 ;
- 两条线段相交 它们在同一个子集中。
这意味着:
- 每个子集内部,所有线段两两相交(形成一个团);
- 不同子集之间,任意两条线段都不相交。
我们要求:从给定的 条线段中,选出一个复杂集合,使得它的大小 最大( 是子集个数)。
核心观察
设:
- = 每个子集中的线段数
- = 子集个数
那么总大小 。
关键:不同子集之间不能相交,所以子集是按“无交区间”排列的。每个子集内,所有线段必须相交于一个公共点(因为所有线段两两相交且都是闭区间)。
第一步:固定 ,求最大
我们定义:
:在给定 的情况下,最多能划分成多少个大小为 的子集(每个子集内全相交,子集间不相交)。
如何计算 ?
算法思路(贪心 + 扫描线)
- 将所有线段按右端点 升序排序。
- 维护一个数组 ,表示位置 当前被多少条“尚未被分配”的线段覆盖。
- 从左到右扫描右端点:
- 当某个点 上的 时,这意味着当前有 条线段都覆盖 ,且它们右端点已处理(按顺序保证了贪心最优),这 条线段可以组成一个子集。
- 将它们从考虑中移除(对应覆盖的点 减 ,其实等价于把它们“清零”)。
更形式化地(标程方法):
- 按 排序后,用懒标记线段树维护每个点被覆盖的次数。
- 每次遇到 ,对区间 加 。
- 当某个位置的值达到 时,收集这些线段形成一个子集,把它们覆盖的区间贡献清零。
这样扫描一遍,可以算出 。
复杂度:对固定的 ,。
第二步:固定 ,求最大
我们也可以反过来:
:给定子集个数 ,每个子集最大可能的大小 。
由于总线段数有限,。
对于固定的 ,我们可以二分 :
- 判断 ?
- 若能,则 可行。
这样对每个 二分,需要 次 调用,每次 ,总 。
第三步:优化 —— 平衡 和
我们目标是最大化 ,且 。
设 。
策略:
- 如果 ,枚举所有 ,计算 ,更新答案。
- 如果 ,枚举所有 ,二分求 ,更新答案。
这样,总计算量:
- 枚举 : 次 ,每次 ,总 。
- 枚举 : 次二分,每次 是 ,总 不对,等等,这里要小心。
更精确:
- 对每个 ,二分需要 次 。
- 所以总时间 $\frac{n}{C} \cdot \log n \cdot (n \log n) = \frac{n^2 \log^2 n}{C}$。
- 代入 :$$\frac{n^2 \log^2 n}{\sqrt{n \log n}} = n^{1.5} \log^{1.5} n。 $$
所以两部分平衡,总复杂度 ,在 时可以接受。
第四步:进一步优化
原题解提到可以用 DSU 优化到 而不是 。
思路:
- 维护一个二进制串,初始全 。
- 支持操作:
- 将位置 设为 ;
- 找 左边最近的 。
- 用 DSU 维护连续 段的父亲,可以 完成。
这样 的每次扫描变成 。
于是总复杂度:
更优秀。
最终算法步骤
- 读入 条线段。
- 预处理:将所有 离散化,保证端点唯一且相对顺序不变。
- 对 :
- 计算 (用 DSU 优化版扫描)。
- 更新答案 $\text{ans} = \max(\text{ans}, m \cdot \text{max\_k}(m))$。
- 对 :
- 二分查找最大 使得 。
- 更新答案。
- 输出答案。
示例验证(题目样例)
以第二个样例:
n=5 l = 1 2 3 6 8 r = 5 4 7 9 10排序后:
手动检查:
- :可以分成 和 ,,总大小 。
- :不够。
- :不可能。
所以答案是 。
总结
本题的核心是:
- 理解复杂集合的结构 ⇒ 子集间无交,子集内全相交。
- 固定 贪心扫描求最大子集数。
- 平衡枚举 和 达到 。
- 用 DSU 进一步优化到 。
- 1
信息
- ID
- 6278
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者