0%

Codeforces Round 788 (Div. 2)——C. Where is the Pizza?

思路讲解(gemini翻译的题解)


首先,我们来解决一个简化版的问题,即假设数组 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 在该索引对应的元素是 1b[1]=1),而 1 已经因为我们最初的选择被包含在数组 c 中了。这样,我们就不再被强制要求从 a 中选择新的元素了,形成了一个闭环。

我们观察到,我们最初选择的元素 1,以及之后被“强制”选择的元素 23,即 [1,3,2](按选择顺序),与它们在 b 数组中对应位置的元素 [3,2,1] 构成了相同元素的排列。这些元素形成了一个“分组”。对于每个大小超过 1 的分组,我们都有 2 个选择:

  1. 将这个分组对应的所有元素都从 a 中选取。

  2. 将这个分组对应的所有元素都从 b 中选取。

所以,这个简化版问题的答案就是:找出所有这样相互关联的分组,统计其中大小超过 1 的分组数量(我们称之为 p),最终答案就是 2p。


那么,如果数组 d 不全是 0 该怎么办呢?

这种情况我们只需要在之前的逻辑上增加一个约束。对于我们找到的每一个分组,我们必须检查其所有成员在 d 数组中对应的位置是否全为 0

  • 如果一个分组对应的所有 d 数组位置上的值都是 0,那么这个分组就有两种选择(要么全选 a,要么全选 b),对最终答案的贡献是乘以 2

  • 如果一个分组中,哪怕只有一个成员在 d 数组中对应的位置不为 0(意味着这个位置的选择已经被 d 数组固定了),那么整个分组的选择也就被唯一确定了,它只有一种选择方案。这种分组对最终答案的贡献是乘以 1,我们就不需要把它计入 p 中。

这个解法可以通过多种方式实现,但在我看来,**使用并查集(Disjoint Set Union, DSU)**来将每个分组的元素合并在一起,是实现这个逻辑最优雅的方式。

AC代码

https://codeforces.com/contest/1670/submission/330958420

心路历程(WA,TLE,MLE……)