QOJ10845 Moving Boxes
有 \(n\) 个箱子,第 \(i\) 个箱子需要从 \(a_i\) 移动到 \(b_i\)。你可以从任意坐标和任意方向出发,每次可以:
- 向当前方向移动,代价为 \(1\)
- 转向,代价为 \(C\)
- 装上当前坐标的节点 / 在当前坐标卸下箱子,这无需代价。
你每时每刻只能携带至多一个箱子。你需要在搬完所有箱子之后回到初始坐标(并保持初始方向)。问最小代价。
\(n \leq 10^6, a_i, b_i \leq 10^9\)。
首先显然会考虑把箱子分成从左往右和从右往左的两种类型。
考虑去尝试构造一个代价的下限。一种有趣的思路是将所有箱子代表的线段 \([a_i, b_i]\) 离散化下来,然后考虑每一个段被经过的次数的下限。
假设一个散段被从左往右的箱子覆盖了 \(p_i\) 次,被从右往左覆盖了 \(q_i\) 次,那么由于路径从左往右和从右往左穿过一个散块的次数一定相等,因此这个散块最少被覆盖 \(2\max\{p_i, q_i, 1\}\) 次。大胆猜测这个下限是可以构造的。
先考虑简单的情况。如果 \(C = 0\) 时,那我们无需考虑方向的改变,那这时把每个散块的下限乘上该散块的长度求和就是答案。
继续考虑 \(C = 1\),由于转向代价很小,容易感觉到我们不会为了减小转向次数而去增大移动的代价,这样一定更劣。因此,考虑计数在最优移动次数下的最优转向次数。
继续把这个转向次数放在散块上去做,考虑相邻两个散块之间的这个交界点最少会发生多少次转向。不妨设 \(cnt_i = 2\max\{p_i, q_i, 1\}\) 表示第 \(i\) 个线段要被从左到右 / 从右到左总共贯穿 \(cnt_i\) 次。
下图考虑了每个与这个交界点有关的移动路径对 \(cnt\) 造成的影响。

容易发现,当在这个交界点发生了转向时,会有一个 \(cnt_{i}\) 减去 \(2\),其他情况是 \(cnt_{i - 1}, cnt_{i}\) 同时减一。为了让转向尽量少,我们一定是要先尽量按照后者来做,因此这时交界点转向次数的下界是 \(|\dfrac{cnt_i}{2} - \dfrac{cnt_{i - 1}}{2}|\)。
接下来的部分就比较容易了。当 \(C\) 可以是任意值的时候,我们是有可能通过多走一些散块让转向次数减少的。因此考虑调整,我们先从移动次数最少的时候考虑。
尝试刻画这个调整的过程,相当于我们可以选择一个散段,然后通过增加 \(cnt_i\),让 \(\sum|\dfrac{cnt_i}{2} - \dfrac{cnt_{i - 1}}{2}|\) 这个值变小。
考虑 \(cnt_i\) 这个序列的连续递增 / 递减的序列。对于一个谷底的连续段,假设这个连续段长度为 \(len\),我们需要操作 \(len\) 次才能让转向次数减少 \(2\)。因此,只有在 \(2C > len\) 时,这个操作才是优秀的。可以考虑直接贪心,每次选取 \(len\) 最短的那些连续段。由于这个 \(len\) 呈现出单调的形态,所以这个贪心的正确性是有保证的。那这题到这里就差不多做完了。
有些实现细节:\(cnt_0\) 和 \(cnt_{m + 1}\) 应该设为 \(0\)。
对于这种思维题,确实很容易陷到里面。大概是要自信一点转变思路的。

浙公网安备 33010602011771号