Dilworth-定理

\(\text{luogu-2501}\)

现在我们有一个长度为 \(n\) 的整数序列 \(a\)。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

\(1 \leq n \leq 3.5 \times 10^4\)\(1 \leq a_i \leq 10^5\)。数据保证 \(a_i\) 随机生成。


感觉比较多 trick 的一道题,记录一下。

第一问可以 \(O(n \log n)\) 解决,反过来考虑,要求最少改变多少个数,可以反过来求最多保留多少个数,钦定 \(i < j\) 那么 \(a_i,a_j\) 能被保留下来,当且仅当 \(a_j - a_i \ge j - i\),即 \(a_i - i \le a_j - j\),令 \(b_i = a_i - i\),那么最多能被保留数的个数就是 \(b\) 序列的最长不降子序列的长度 \(len\),那么答案就是 \(n - len\),计算最长不降子序列的长度可以 \(O(n \log n)\) 解决,可以参考 luogu-1020 导弹拦截这道题。

也是一个非常经典的题,大致流程大概是这样,维护一个单调栈,遍历 \(b\) 序列,若 \(b_i \ge s_{top}\) 则直接压入栈;否则就找到栈内第一个大于 \(b_i\) 的数 \(s_x\),然后 \(s_x \gets b_i\)。最终单调栈 \(s\) 的长度就是答案。

至于正确性,记 \(l_i\) 表示以 \(b_i\) 为结尾的最长不降子序列的长度,若处理完前 \(i\) 个数,此时 \(s_x = b_i\),那么 \(l_i = x\),最终答案就是 \(\max l_i\),也就是过程中单调栈长度的最大值,又因为这个单调栈没有 pop 操作,所以答案就是最终的单调栈长度。

第二问求的实际上是一种最优保留方案的最小改变值,钦定一种方案保留了下标 \(\{c_1, c_2, \cdots, c_{len}\}\) 的这些 \(b_{c_i}\),那么对于两个相邻的 \(c_i,c_{i+1}\),中间的数就需要调整,显然这些数 \(b_j\) 满足 \(b_j < b_{c_i}\)\(b_j > b_{c_{i+1}}\)

存在一个分界点 \(k,(c_i < k < c_{i+1} - 1)\),将 \(k\) 及之前的 \(b_j\) 都改为 \(b_{c_i}\)\(k\) 之后的 \(b_j\) 都改为 \(b_{c_{i+1}}\),可以证明这样一定是最优的调整方案,具体证明可以参考 这篇题解,讲得很详细。

\(f_i\) 表示处理完前 \(i\)\(b_i\) 的最优答案,那么转移就是这样:

\[f_i = \min_{l_j + 1 = l_i \wedge b_j \le b_i \wedge i < j} \left(f_j + \min_{i \le k < j} \left(\sum_{w=j+1}^k |b_w - b_j| + \sum_{w=k+1}^i |b_w - b_i|\right)\right) \]

另外最左边和最右边都可能转移到,需要设置哨兵节点 \(b_0,b_{n+1}\)

前后缀和预处理优化一下,计算这个式子看起来是接近 \(O(n^3)\) 的,因为需要枚举 \(i,j,k\),但因为数据随机,满足 \(l_j + 1 = l_i\) 条件的 \(j\) 期望数量很少,已经可以通过这道题了。


我们考虑一些额外的东西。

可以用 vector 记录下长度为 \(x\) 的所有下标,然后就可以不遍历那些不合法的 \(l_j\),但也可能遍历到 \(j \ge i\) 的情况,不过这样处理的好处是可以直接输出所有方案,虽然这题不需要。

还有一种记录方案的方式,考虑压入单调栈的时候记录栈顶下标为前驱;修改单调栈元素之后记录插入位置之前的下标为前驱,同步记录一个下标的单调栈就好了,正确性也可以证明。这种方式没办法记录所有方案,不过一般情况也够用了。比上一种方式好写一点。

然后借 luogu-1020 顺便复习一下 Dilworth 定理,定理内容是,对于任意有限偏序集,其最长反链长度等于最小链覆盖数。应用到这题上,要求最少用多少导弹系统,实际上就是求“最小链覆盖”,等于最长反链长度,因为链指的是最长不升子序列,那么反链就是指最长上升子序列,也就是只需要求最长上升子序列长度即可。

由于要求严格上升,所以单调栈也得遵循严格上升,若当前值 \(x\) 不大于栈顶,我们要检查一下是否单调栈里已经有 \(x\),没有的话再替换第一个大于 \(x\) 的数,这个过程可以简化为把 upper_bound 改成 lower_bound。

posted @ 2026-05-10 21:52  So_noSlack  阅读(10)  评论(0)    收藏  举报