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]\) 的区间左右端点来,相当与取一个最小或一个最大,只需要记录区间的左右端点,就能从后向前还原序列。

浙公网安备 33010602011771号