Loading

11.22 CW 模拟赛 T3.重复

算法

考虑 \(\rm{dp}\)

其实谁都知道是 \(\rm{dp}\) , 但是推不出来啊

这个问题的关键点在于注意到每次往回走, 必定需要走到之前只访问过一次的位置, 这样算法才有正确性

容易的, 令 \(f_i\) 表示游览结束前 \(i\) 个点的最小时间花费, 由上面的结论可知, 对于 \(f_i\) 往回走的更新, 一定可以用 \(f_j, j < i\) 来表示, 因为是最小的花费, 显然 \(f_i\) 时刻在 \(i\) 点的位置

考虑转移
注意到仅仅有这样的情况:
先往前走到 \(i\) ( 再往后走是无意义的, 一定不优 ) , 然后在回头走, 最后再绕回 \(i\)
这样有一个问题在于有可能绕回来的过程中依然没有到达时间限制 \(T\) , 于是必须要等到 \(T\) , 此时路过的点一定能够全部访问

在这里我有一个误区, 就是同时考虑了往前走在走回来这一情况, 事实上考虑一种即可覆盖

有转移柿子

\[f_i = \min_{j = 1}^{i - 1} \left\{ f_j + a_i - a_j + \max \left[ 2 \times (a_i - a_{j + 1}), T) \right] \right\} \]

显然的, 有 \(f_1 = \max(a_1, T)\) , 答案即为 \(f_n\)

但是这样做是 \(\mathcal{O} (n ^ 2)\) 的, 我们考虑优化

数据结构优化

不太显然的, 将转移柿子中的 \(a_i - a_j\) 提出

有,

\[f_i = a_n + \min_{j = 1}^{i - 1} \left\{ f_j + \max \left[ 2 \times (a_i - a_{j + 1}), T) \right] \right\} \]

直接丢进堆里维护即可, 复杂度 \(\mathcal{O} (n \log n)\)

利用单调性优化

需要一些注意力, 我们观察到 \(i\) 一定时, \(2 \times (a_i - a_{j + 1})\)\(f_j\) 是单调递减的, 同时, 注意到当 \(i\) 增加时, 在之前 \(2 \times (a_i - a_{j + 1}) > T\) , 对于更大的 \(i ^ {\prime}\) 显然也有 \(2 \times (a_{i ^ {\prime}} - a_{j + 1}) > T\)

那么我们就可以想到一种做法, 对于每一次更新 \(a_i\) , 我们就在单调队列中把所有满足 \(2 \times (a_i - a_{j + 1}) > T\)\(j + 1\) 弹出, 其中 单调队列按照 \(a_i\) 从小到大排序

弹出点的时候, 记录其最大值 \(k\) , 然后对于队列中的点, 有
$ f_i = a_n + f_j + T $ , 对于弹出的点, 有 \(f_i = a_n + f_j + 2 \times (a_i - k)\)

每个点进队出队一次, 时间复杂度 \(\mathcal{O} (n)\)

事实上因为 \(a_i\) 单调性, 完全可以使用队列处理

代码

略了, 好累啊

总结

有啥好说的, 练 \(\rm{dp}\)

注意考虑转移时不需要考虑本质相同的转移

写博客就该这样, 不能看着题解抄, 自己理一遍

posted @ 2024-11-22 19:58  Yorg  阅读(12)  评论(0)    收藏  举报