题解:P11546 [BalticOI 2009] 糖果机器 (Day1)
AT_doming_Cl2 · · 题解
题目大意
有
条件转化
前轱辘不转后轱辘转,那题目本身看不懂,就先转换为数学式子呗。
设一辆收集车依次接住了糖果
把恶心的绝对值拆开:
定义每个糖果的两个特征值:
那么一辆收集车可以先后接住
换句话说,如果将糖果按照被同一辆车接住的顺序排成一个序列,这个序列在
因此问题转化为:
平面上有
n 个点(A_i, B_i) ,要用最少的不降链覆盖所有点。这里“不降链”指序列中A 、B 均不降。
最小链覆盖与 Dilworth 定理
在偏序集(poset)中,链是一个两两可比较的元素序列,反链是一个两两不可比较的集合。对于本题,定义偏序关系:
链就是可以被同一辆车依次接住的糖果序列,反链就是任意两个糖果都不能被同一辆车接住(即必须用不同车辆)。
Dilworth 定理指出:有限偏序集的最小链覆盖数等于最长反链的长度。
因此,最少收集车数量 = 最长反链大小。
这里的最长反链,等价于从点集中选出尽可能多的点,使得它们两两不可比较。这正好可以用二维偏序的经典方法求出,例如对第一维排序后求第二维的最长下降子序列(因为不可比较意味着
However,本题还需要输出具体每颗糖果由哪辆车接住,也就是要求出链覆盖方案。我们可以用贪心构造的方法直接得到方案,同时自然得到最小链数(车辆数)。
贪心构造算法
将所有糖果按照
维护当前每辆收集车最后接住的糖果的
- 在已有的车中,找一辆最后
B 值小于等于当前B 的车,并且选最后B 值最大的那一辆。 - 如果找到,就把该糖果分配给这辆车,并更新该车的最后
B 值为当前B 。 - 如果找不到,就新增一辆收集车,并设置其最后
B 为当前B 。
这个贪心过程和经典的“导弹拦截”第二问完全一致,正确性可由 Dilworth 定理及贪心性质保证。算法结束时,使用的车辆数就等于最长反链长度,也就是最小链覆盖数。
使用 set 维护所有 (last_B, machine_id) 对,每次在 set 中二分查找最后一个
::::info[AI 使用情况披露] 本题解使用了 DeepSeek 进行润色。 ::::