假设给出数列 a,求一个单调不降的数列 b,要求最小化 ∑|ai−bi|。
如果 a 是单调不减的数列,考虑 b 的构造方式,如图:
那么所有的 b 要取同一个值。先假定取当前 a 序列的中位数(中位数的定义是将 a 从小到大排序后,第 ⌈n2⌉个数),发现如果将 b 的那条线向上移动,那么与 a 线的交点就会往左移,也就是说,与 b 线距离增加的点数增加了,与 b 线距离减少的点数减少了。将线往下移同理。所以说此时 b 取中位数最优。
但是现在 a 序列不是单调不增的,我们就把它划分成若干个单调不增的序列,每一个序列取一个 b。现在的问题就是,这些 b 之间不是单调不减的。
考虑两个单调不增序列 A1和 A2,其中 A1的中位数较大,A2的中位数较小。同样画图分析
解释一下,中间的线如果不是平的,那么将左边的线往上移,右边的往下移,都可以使得与这个线距离变小的点增加,会产生更优秀的方案。
那么这两个区间合并,找到的所有 b 也一定相同。那么此时可以将这两个区间看作一个处理,我们已经证明过整个区间的 b 都相同时,取中位数最优,所以我们就要取这两个区间的中位数当 b。
那么怎么实现快速合并中位数呢?使用左偏树。每次开个大根堆,当堆中元素数量大于这个堆代表的区间的元素数量的一半时,不断弹出堆顶元素,这样堆顶的元素就是中位数了。合并两个区间相当于合并两个堆。
嗯,最后,我们将这个问题改回求的 b 是单调上升序列,那么我们可以认为我们每次在求一个 i+bi,bi单调不降。也就是将每个 ai减去 i,然后其他做法完全相同。
1 条评论
【题解】 K凹凸序列 可并堆 BZOJ – 2171 – K-XZY · 2018年12月14日 10:22 上午
[…] k=2,同 bzoj1367 sequence,只不过把问题中的上升改成不降(以及不升)[…]