加载中...

ABC 444 F (中位数二分+贪心)

F - Half and Median

Q:有 \(n\) 个木棍,第 \(i\) 条木棍的长度为 \(a_{i}\),需要执行恰好 \(m\) 次折木棍操作:每次操作可以选任意一根长度 \(\geq 2\) 的木棍,将其折成两半(长为奇数则折成原长除 \(2\) 的上取整与下取整;长为偶数则折成长度相同的两部分。数据保证可以至少折 \(m\) 次)。最大化操作后 \(n + m\) 根木棍的长度的中位数。数据额外保证 \(n + m\) 一定是奇数(应该是为了避免偶数时中位数可能是小数的情况)。

看到中位数,显然优先考虑二分。对于长度 \(X\),答案 \(\geq X\) 的充要条件是存在一种操作方案,使得操作后长度 \(\geq X\) 的木棍数量至少为 \(\frac{n+m+1}{2}\)

由于每次切割木棍时只能对半分,我们可以证明对于任意长度为 \(A\) 的木棍,在其切割过程中可能出现的木棍长度种类数为 \(O(\log A)\)。因此,我们不妨模拟整个切割过程,每次贪心切分当前木棍集合中最长的木棍,对于多根长度相同的木棍合并在一起模拟,这样能保证最多枚举 \(O(n\log A)\)

对于正在二分的长度 \(X\),我们目标是:

  • 分割结束后,长度 \(\geq X\) 的木棍至少 \(\frac{n+m+1}{2}\)
  • 总木棍数量恰好为 \(n + m\),也就是能够至少分割 \(m\)

我们可以先去分割长度 \(\geq 2X-1\) 的所有木棍,因为分割它们总是能保证长度 \(\geq X\) 的木棍数量不减,并且增加分割次数,一定不劣;模拟完切割过程后,我们先 check 长度在 \([X, 2X-1)\) 之间的木棍数量是否 \(\geq \frac{n+m+1}{2}\),不满足则返回 false(因为长度 \(\geq X\) 的木棍不能再增多了);若满足,也不可以直接返回 true,因为还没有保证至少切割了 \(m\) 次。为了在满足条件一的情况下尽可能地增大切割次数,我们考虑保留所有长度 \(\geq X\) 的木棍中最短的 \(\frac{n+m+1}{2}\)然后尽可能地将剩下的木棍做无限制的切割,也就是全切成长度为 \(1\) 的木棍。显然这样做可以在保证条件一满足的情况下,最大化条件二满足的可能性,是最优解。判断剩下的木棍能操作多少次,可以直接用 剩下木棍的总长度-剩下木棍的数量 简单得到(证明略)。按照上述模拟,最后 check 总操作次数是否 \(\geq n + m\) 即可。具体实现见 code。

注意本题很卡常,在 check 内模拟切割木棍过程时尽量不要用 map 粗暴模拟,推荐先将切割过程中所有可能出现的长度数值离散化,做一些预处理后再用数组模拟,可以省去一个 \(\log\) 的复杂度。

复杂度分析:主要来自于模拟切割过程的复杂度 \(O(n\log^{2}(\max(A_{i})))\)

code

posted @ 2026-02-11 16:01  小橘奏  阅读(29)  评论(0)    收藏  举报