1 条题解

  • 0
    @ 2026-4-2 22:13:48

    题目重述(便于理解)

    nn 条线段 [li,ri][l_i, r_i]

    一个线段集合称为复杂集合,如果它可以划分成若干个子集,使得:

    1. 所有子集的大小相同,设为 mm
    2. 两条线段相交     \iff 它们在同一个子集中。

    这意味着:

    • 每个子集内部,所有线段两两相交(形成一个团);
    • 不同子集之间,任意两条线段都不相交。

    我们要求:从给定的 nn 条线段中,选出一个复杂集合,使得它的大小 m×km \times k 最大(kk 是子集个数)。


    核心观察

    设:

    • mm = 每个子集中的线段数
    • kk = 子集个数

    那么总大小 =mk= m \cdot k

    关键:不同子集之间不能相交,所以子集是按“无交区间”排列的。每个子集内,所有线段必须相交于一个公共点(因为所有线段两两相交且都是闭区间)。


    第一步:固定 mm,求最大 kk

    我们定义:

    max_k(m)\text{max\_k}(m):在给定 mm 的情况下,最多能划分成多少个大小为 mm 的子集(每个子集内全相交,子集间不相交)。

    如何计算 max_k(m)\text{max\_k}(m)

    算法思路(贪心 + 扫描线)

    1. 将所有线段按右端点 rir_i 升序排序。
    2. 维护一个数组 cnt[x]cnt[x],表示位置 xx 当前被多少条“尚未被分配”的线段覆盖。
    3. 从左到右扫描右端点:
      • 当某个点 pp 上的 cnt[p]=mcnt[p] = m 时,这意味着当前有 mm 条线段都覆盖 pp,且它们右端点已处理(按顺序保证了贪心最优),这 mm 条线段可以组成一个子集。
      • 将它们从考虑中移除(对应覆盖的点 cntcntmm,其实等价于把它们“清零”)。

    更形式化地(标程方法):

    • rr 排序后,用懒标记线段树维护每个点被覆盖的次数。
    • 每次遇到 rir_i,对区间 [li,ri][l_i, r_i]11
    • 当某个位置的值达到 mm 时,收集这些线段形成一个子集,把它们覆盖的区间贡献清零。

    这样扫描一遍,可以算出 max_k(m)\text{max\_k}(m)

    复杂度:对固定的 mmO(nlogn)O(n \log n)


    第二步:固定 kk,求最大 mm

    我们也可以反过来:

    max_m(k)\text{max\_m}(k):给定子集个数 kk,每个子集最大可能的大小 mm

    由于总线段数有限,mknm \cdot k \le n

    对于固定的 kk,我们可以二分 mm

    • 判断 max_k(m)k\text{max\_k}(m) \ge k
    • 若能,则 mm 可行。

    这样对每个 kk 二分,需要 O(logn)O(\log n)max_k(m)\text{max\_k}(m) 调用,每次 O(nlogn)O(n \log n),总 O(nlog2n)O(n \log^2 n)


    第三步:优化 —— 平衡 mmkk

    我们目标是最大化 mkm \cdot k,且 mknm \cdot k \le n

    C=nlognC = \sqrt{n \log n}

    策略

    • 如果 mCm \le C,枚举所有 m=1Cm = 1 \dots C,计算 max_k(m)\text{max\_k}(m),更新答案。
    • 如果 knCk \le \frac{n}{C},枚举所有 k=1nCk = 1 \dots \frac{n}{C},二分求 max_m(k)\text{max\_m}(k),更新答案。

    这样,总计算量:

    • 枚举 mmCCmax_k(m)\text{max\_k}(m),每次 O(nlogn)O(n \log n),总 O(Cnlogn)=O(n1.5log1.5n)O(C \cdot n \log n) = O(n^{1.5} \log^{1.5} n)
    • 枚举 kknC\frac{n}{C} 次二分,每次 max_k\text{max\_k}O(nlogn)O(n \log n),总 O(nCnlog2n)O(\frac{n}{C} \cdot n \log^2 n) 不对,等等,这里要小心。

    更精确:

    • 对每个 kk,二分需要 O(logn)O(\log n)max_k\text{max\_k}
    • 所以总时间 $\frac{n}{C} \cdot \log n \cdot (n \log n) = \frac{n^2 \log^2 n}{C}$。
    • 代入 C=nlognC = \sqrt{n \log n}:$$\frac{n^2 \log^2 n}{\sqrt{n \log n}} = n^{1.5} \log^{1.5} n。 $$

    所以两部分平衡,总复杂度 O(n1.5log1.5n)O(n^{1.5} \log^{1.5} n),在 n2×104n \le 2\times 10^4 时可以接受。


    第四步:进一步优化 max_k(m)\text{max\_k}(m)

    原题解提到可以用 DSU 优化到 O(nα(n))O(n \alpha(n)) 而不是 O(nlogn)O(n \log n)

    思路:

    • 维护一个二进制串,初始全 11
    • 支持操作:
      1. 将位置 pp 设为 00
      2. pp 左边最近的 11
    • 用 DSU 维护连续 00 段的父亲,可以 O(α(n))O(\alpha(n)) 完成。

    这样 max_k(m)\text{max\_k}(m) 的每次扫描变成 O(nα(n))O(n \alpha(n))

    于是总复杂度:

    O(n1.5α(n))O(n^{1.5} \alpha(n))

    更优秀。


    最终算法步骤

    1. 读入 nn 条线段。
    2. 预处理:将所有 li,ril_i, r_i 离散化,保证端点唯一且相对顺序不变。
    3. m=1nlognm = 1 \dots \sqrt{n \log n}
      • 计算 max_k(m)\text{max\_k}(m)(用 DSU 优化版扫描)。
      • 更新答案 $\text{ans} = \max(\text{ans}, m \cdot \text{max\_k}(m))$。
    4. k=1n/nlognk = 1 \dots \lfloor n / \sqrt{n \log n} \rfloor
      • 二分查找最大 mm 使得 max_k(m)k\text{max\_k}(m) \ge k
      • 更新答案。
    5. 输出答案。

    示例验证(题目样例)

    以第二个样例:

    n=5
    l = 1 2 3 6 8
    r = 5 4 7 9 10
    

    排序后:

    • [1,5],[2,4],[3,7],[6,9],[8,10][1,5],[2,4],[3,7],[6,9],[8,10]

    手动检查:

    • m=2m=2:可以分成 {[1,5],[2,4]}\{[1,5],[2,4]\}{[6,9],[8,10]}\{[6,9],[8,10]\}k=2k=2,总大小 44
    • m=3m=3:不够。
    • m=4m=4:不可能。

    所以答案是 44


    总结

    本题的核心是:

    1. 理解复杂集合的结构 ⇒ 子集间无交,子集内全相交。
    2. 固定 mm 贪心扫描求最大子集数。
    3. 平衡枚举 mmkk 达到 O(n1.5log1.5n)O(n^{1.5} \log^{1.5} n)
    4. 用 DSU 进一步优化到 O(n1.5α(n))O(n^{1.5} \alpha(n))
    • 1

    信息

    ID
    6278
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    递交数
    1
    已通过
    1
    上传者