首先考虑指数级算法。枚举集合 S 表示最后权值计入答案的区间。设 L=i∈Smin{ri},R=i∈Smax{ri}。为了使 S 合法,所有 L<li<R 的区间在 [L,R] 内的部分均需被封印,且所有 S 中的区间均需被完整封印,其余区间均可被完全放弃(即在 li 被放弃)。
进一步地,可以认为 L<li<R<ri 的区间也被完整封印,因为如果大于 R 的时刻出现超过 K 个这种区间,那么它们也会使 R−1 时刻不合法。
检查是否存在时刻被覆盖超过 K 次即可。
时间复杂度 O(2nn),期望通过子任务 1。
算法二
先考虑所有区间权值均为 1 的情况。
上面的朴素算法提供了思路,最后计入答案的区间集合数量是指数级的,但集合对应的 [L,R] 很少。
枚举 [L,R],区间可被分为六类:
I 类:li≤L≤ri≤R;
II 类:li≤L≤R<ri;
III 类:L<li<ri≤R;
IV 类:L<li<R<ri;
V 类:li≥R;
VI 类:ri<L。
其中,III,IV 类区间一定被完整封印,同时 III 类区间必须计入答案。除此之外,可以完整封印一些 I 类区间以使答案更大。
定义 [L,R] 合法当且仅当所有 III,IV 类区间没有使得一个时刻被覆盖超过 K 次,容易发现对于固定的 L,合法的 R 一定是 L 开始的若干连续正整数。进一步,如果 [L,R1] 和 [L,R2] 均合法且 R1<R2,那么 [L,R2] 对应答案一定不劣。证明如下:在 [L,R1] 最优答案中的 I 类区间集合 S,那么 [L,R2] 相对于 [L,R1] 多出的 III,IV 类区间都有 li≥R1,所以它们和 S 中的区间都不交,故在 [L,R2] 时选择 S 中的所有区间也合法。
现在要考虑的 [L,R] 只有 O(n) 个,注意到 R 随 L 增大单调不减,故可以用尺取法加上线段树来 O(nlogn) 求出这些 [L,R]。
对于每个 [L,R],显然取的 I 类区间按 ri 排序后一定是一个前缀。所以对于这 O(n) 个 [L,R],分别将对应的 I 类区间按 ri 从小到大尝试加入即可。
时间复杂度 O(n2logn),期望通过子任务 2。
算法三
算法二的瓶颈在于每次重新尝试加入 I 类区间,现在考虑在尺取过程中维护。尺取可以拆成 L 右移和 R 右移,下面分开考虑会对区间类别产生什么影响。
L 右移:(a) I→VI;(b) III→I;(c) IV→II。
R 右移:(d) II→I;(e) IV→III;(f) V→IV。
记答案中选取的 I 类区间集合为 S,所有 III,IV 类区间集合为 T。
(a) 中如果被移除的 I 类区间如果在 S 中,移除后显然最多再加入一个 I 类区间到 S 中。用小根堆维护所有不在 S 中的 I 类区间,尝试加入 ri 最小的那个即可。
(b)(c) 都可以看作是先删除了一个 li=L 的 T 中区间。这其实和删除一个 S 中的区间产生的影响类似,可以说明此时也只会再加入一个区间到 S 中。对于 (b),还要再加入一个 I 类区间。此时如果它的 ri 比 S 中最大的 r 小,将它加入 S,然后若产生不合法则删去 S 中 r 最大的区间,这部分可以用大根堆维护 S 中区间;否则加入小根堆,并尝试将堆顶加入 S。
(d) 由于这个发生改变的区间满足 ri=R,所以不会将 S 中的区间“顶替掉”。只要把它加入小根堆,并尝试加入当前 ri 最小的 I 类区间即可。
对于权值在 (wj,wi) 中的区间,假设此时原来不在 S 中的区间 k 可以加入,设 S 中所有权值小于 wj 的区间集合为 A,那么由于 j,k∈/S,所以 ∀a∈A,ra<rj,ra<rk,那么 j,k 对 A 中区间的限制等效,故 k 也可加入 S∖{i},与 j 的最大性矛盾;
对于权值小于 wj 的区间,由于删去的 i 满足 ri=L−1 是现在所有 I 类区间中最小的,故将 i 替换成 j 后限制更严,但由于 j 能加入 S∖{i},所以这部分区间是否加入也没有变化。