[IOI2016]railroad

题面

\(n\) 个二元组,第 \(i\) 个为 \(a_i,b_i\)

对于一个 \(1\sim n\) 的排列 \(p\),定义其权值为:

\[\sum_{i=1}^{n-1}\max(a_{p_i}-b_{p_{i+1}},0) \]

求出最小权值排列的权值。

数据范围 :\(n\le 2\times 10^5\)

题解

先加入一个 \((\inf,0)\) 的点,然后把排列改为环(也就是 \(p_1\)\(p_n\) 也要计算贡献)。

然后就是一个很神奇的转换:

我们可以把权值离散化之后看成点,\(i\)\(i+1\) 之间有边,正向走 \(i\rightarrow i+1\) 边权 \(0\) ,反向走 \(i+1\rightarrow i\) 边权为相邻权值的差,然后把一个二元组看做一个必须要走的边,然后在这个图上走一个最短欧拉回路就是答案。

为什么?

你可以把当前在的点看作是一个参数,选一个二元组看做把当前的 \(a_i\) 强制转换为 \(b_i\) ,然后在两个二元组之间的改变参数所需要的代价就是权值计算公式。

所以现在的问题就是解决这个最短欧拉回路问题了。

不知道这是不是一个经典问题...

因为我们有一些必走边,我们可以最开始认为走了这些边,然后用两点之间的边去把这些边连为一条路径。

既然是一个欧拉回路,那么对于一个必走边 \(a_i\rightarrow b_i\) ,一定要走一次回来的路。

那么对于一个边 \(i,i+1\) ,如果覆盖了这条边的向左的 必选边 和向右的 必选边 数量不一致,那么就一定需要向左/向右走,加上对应的代价就行。

做完这个操作之后我们会得到若干个存在欧拉回路的联通块,但是原图还没有欧拉回路。我们还需要把联通块连起来,这个操作每次要连一条先右的和一条向左的。

显然我们只会在相邻的联通块之间连边,否则一定不优,扫一遍加边,然后跑最小生成树即可。

扩展

如果贡献改为:

\[\sum_{i=1}^{n}|a_{p_i}-b_{p_{(i\ \bmod\ n)+1}}| \]

那么我们就不用加入新的二元组,把正向走 \(i\rightarrow i+1\) 边权也改为权值之差就行。

启发

  • 对于一系列排列权值的问题都可以这么做,只要权值计算方式是线性的。
  • 后面的欧拉回路问题也是很巧妙的题。
posted @ 2022-06-17 09:40  qwq_123  阅读(42)  评论(0编辑  收藏  举报