atcoder ABC406 部分题解

F - Compare Tree Weights

题目

用 dfs 序遍历树,一个树的子树就是 dfs 序的一个区间,查子树和即求序列的区间和。

代码

G - Travelling Salesman Problem

题目

特别好的 slope trick 。

\(f_{i,j}\) 为前 \(i\) 个商人最后落点在 \(j\) 的最优方案,转移为:

\[f_{i,j}=\min(f_{i-1,k}+C|j-k|+D|j-a_i|) \]

可以通过下面的解法归纳证明该函数是凸函数。

考虑 \(C|j-k|\) ,其实时上是将斜率小于 \(-C\) 和大于 \(C\) 的位置斜率拍成 \(C\) ,任何斜率小于 \(-C\) 大于 \(C\) 的位置可以由最近的一个位置转移过来,斜率在 \([-C,C]\) 的位置从自己转移就是最优的。

再考虑 \(D|j-a_i|\) ,就是将 \([-\infty,a_i]\) 的斜率加 \(-D\)\([a_i+1,+\infty]\) 的位置斜率加 \(D\)

可以用线段树维护 \(f_i\) 的差分,即斜率。并任意记录一个位置的实际值,这里为了方便可以记录 \(-\infty\) 位置的实际值(在本题中可以记录 \(-10^5\) 位置),最后走所有的负斜率走到最低处还原答案。

注意 \(-\infty\) 位置的值不是简单的将每个商人都挪到该位置,人从一开到该位置就不动了。考虑在 \(C|j-k|\) 的转移中,可以从最近的斜率大于等于 \(-C\) 转移过来,所以还需要求一个前缀的斜率和更新 \(-\infty\) 的值。

最后还要输出方案,\(D|j-a_i|\) 不影响方案,\(C|j-k|\) 即为将一个前缀和后缀位置的转移从 \([-C,C]\) 的区间左右端点来,相当与取一个最小或一个最大,只需要记录区间的左右端点,就能从后向前还原序列。

代码

posted @ 2025-06-20 19:54  蒻蒻虫  阅读(9)  评论(0)    收藏  举报