思路讲解
精髓在于猜这个你随机跳到其他位置以后,再跳到终点N+1的期望成本,可以设这个东西位S,用这个S算出来的S,我们叫做g(S)。那么 那是必须的,但是我们猜的不等于怎么办呢?
于是我们就二分。
至于这个二分的收敛方向嘛,我试着推了一下,我的建议是都试试。guess嘛。

这个图把y=x画的太斜了,实际上在y=x的下面,,需要向左移动(也就是even<mid,r=mid)。
1 | // 从x到N+1的最小期望成本 |
AC代码
1 |
精髓在于猜这个你随机跳到其他位置以后,再跳到终点N+1的期望成本,可以设这个东西位S,用这个S算出来的S,我们叫做g(S)。那么 g(S)=S 那是必须的,但是我们猜的不等于怎么办呢?
于是我们就二分。
至于这个二分的收敛方向嘛,我试着推了一下,我的建议是都试试。guess嘛。

这个图把y=x画的太斜了,实际上在y=x的下面,g(S)<S,需要向左移动(也就是even<mid,r=mid)。
1 | // 从x到N+1的最小期望成本 |
1 |
赛后自己想出来了
核心代码是
1 | FOR(i,1,N){ |
https://acm.hdu.edu.cn/contest/view-code?cid=1175&rid=12705
1 | // by Gospel_rock |
首先,我们来解决一个简化版的问题,即假设数组 d 中全是 0(换句话-说,对于需要形成的排列 c 没有任何预设的限制)。
我们假设排列 a 为 [1,2,3,4],排列 b 为 [3,1,2,4]。
假设我们已经选择了数组 c 的第一个元素为数组 a 的第一个元素(即 c[0] = a[0] = 1)。这样一来,我们就不能选择数组 b 的第一个元素了(b[0] = 3)。由于我们希望数组 c 是一个完整的排列,那么数字 3 就必须在 c 中出现,所以我们必须从数组 a 中找到 3 并将其加入到数组 c 中。
我们在数组 a 中寻找 3,发现它在索引 2 的位置(a[2]=3),于是我们选择 c[2] = a[2] = 3。这个选择导致我们不能再选择 b 中对应索引的元素(即 b[2]=2)。因此,我们又必须从 a 中找到 2 并加入 c。我们在 a 中找到 2 在索引 1 的位置(a[1]=2),所以选择 c[1] = a[1] = 2。这次,b 在该索引对应的元素是 1(b[1]=1),而 1 已经因为我们最初的选择被包含在数组 c 中了。这样,我们就不再被强制要求从 a 中选择新的元素了,形成了一个闭环。
我们观察到,我们最初选择的元素 1,以及之后被“强制”选择的元素 2 和 3,即 [1,3,2](按选择顺序),与它们在 b 数组中对应位置的元素 [3,2,1] 构成了相同元素的排列。这些元素形成了一个“分组”。对于每个大小超过 1 的分组,我们都有 2 个选择:
将这个分组对应的所有元素都从 a 中选取。
将这个分组对应的所有元素都从 b 中选取。
所以,这个简化版问题的答案就是:找出所有这样相互关联的分组,统计其中大小超过 1 的分组数量(我们称之为 p),最终答案就是 2p。
d 不全是 0 该怎么办呢?这种情况我们只需要在之前的逻辑上增加一个约束。对于我们找到的每一个分组,我们必须检查其所有成员在 d 数组中对应的位置是否全为 0。
如果一个分组对应的所有 d 数组位置上的值都是 0,那么这个分组就有两种选择(要么全选 a,要么全选 b),对最终答案的贡献是乘以 2。
如果一个分组中,哪怕只有一个成员在 d 数组中对应的位置不为 0(意味着这个位置的选择已经被 d 数组固定了),那么整个分组的选择也就被唯一确定了,它只有一种选择方案。这种分组对最终答案的贡献是乘以 1,我们就不需要把它计入 p 中。
这个解法可以通过多种方式实现,但在我看来,**使用并查集(Disjoint Set Union, DSU)**来将每个分组的元素合并在一起,是实现这个逻辑最优雅的方式。
https://codeforces.com/contest/1670/submission/330958420
1 | // Problem: C. Where is the Pizza?C. 披萨在哪里? |
2025“钉耙编程”中国大学生算法设计暑期联赛(3)(2025杭电多校 3)——1009线段染色
和这道题目有点相似,难点都在于这个容斥上面,那么解决都很简单,就是上dp。
1 |