题解 - UER #14 T2 果冻
首先,这个“修改会保留”完全没用。你每次如果想问原数组修改 \(S\) 的结果,那就去问 \(S \operatorname{xor} lst\) 就好。其中 \(lst\) 为上次询问的东西。
考虑先确定两个 \((1, n)\) 的位置。可以发现,两个 \((1, n)\) 相位不同(一个 \(1\) 在上一个 \(1\) 在下)和答案为 \(n - 1\) 是等价的。因此,改变恰好一个 \((1, n)\) 的相位会导致【答案是否为 \(n - 1\)】这件事反转。就此,我们随机一个大小为 \(\frac{n}{2}\) 的集合,如果反转了,那一定是集合内一个 \((1, n)\),集合外一个 \((1, n)\)。两次二分即可。只需要花费 \(2 \log n + O(1)\) 次。
确定了两个 \((1, n)\) 的位置之后,将他们的相位都变成 \(n\) 在上(如果原先一上一下,令接下来的所有询问都将 \(n\) 在下的那个位置反转即可)。然后,【答案是否为 \(n - 2\)】就和【是否至少存在一个 \(2\) 在上面】等价了。我们考虑此时确定出两个 \((2, n - 1)\) 的位置。先完全用原数组问一次,再将原数组中除了已经确定的两个 \((1, n)\) 的位置以外的位置都反转之后问一下。显然,如果两次都是 \(n - 2\) 说明一上一下,仅第一次是 \(n - 2\) 说明两个 \(2\) 在上,仅第二次是 \(n - 2\) 说明两个 \(2\) 在下。先考虑简单的两个都在上/下:
如果两个都在上,我们把接下来的询问都取反,来让两个都在下。此时,我们可以直接二分。选择没确定的所有位置中的一半反转,如果变成了 \(n - 2\) 就说明这里面有 \(2\),二分到底就找到一个 \(2\),然后扔掉这个位置再二分一次找到第二个 \(2\) 即可。
如果一上一下比较麻烦,我们考虑这个策略:先枚举 \(d\),把二进制第 \(d\) 位为 \(1\) 的分为一组,剩下的是另一组。分别问仅反转一组时的答案。如果都是 \(n - 2\) 说明两个 \((2, n - 1)\) 位于同一组,先不管。否则,答案不为 \(n - 2\) 的那组出现了 \(2\) 在上的 \((2, n - 1)\),直接二分,朝着答案不为 \(n - 2\) 的方向走。另一组呢?先全都反转,然后同样二分。这样询问次数时 \(2 \log n + d\),可以卡到 \(3 \log n\),然后总体就 \(3 \log n * \frac{n}{2}\) 倒闭了。怎么办?其实第二次二分不用从头开始。我们知道了两个 \((2, n - 1)\) 的二进制前 \(d - 1\) 位都一样,所以第二个 \((2, n - 1)\) 只有 \(2^{\log n - d}\) 个可能的取值,在这个范围里二分,总次数就是 \(d + \log n + (\log n - d) = 2 \log n\) 了,这就对了。
显然 \(2\) 的这个过程可以推广到 \(3, 4, ..., \frac{n}{2}\),所以总共进行 \(\frac{n}{2} - 1\) 次这个过程。对于 \(n\) 是奇数,最后会剩一个没确定的位置,肯定是 \(\frac{n + 1}{2}\)。
总询问 \((2 \log n + 2)(\frac{n}{2} - 1) + 2\log n + O(1) = (\log n + 1) n + O(1)\),看似正好超一点,但是由于跑的过程中 \(\log n\) 的那个 \(n\) 会减少,所以前面那个巨大的东西会空余。认真分析应该是 \(n\log n + O(1)\)(后一半 \(\log n\) 可以少 \(1\),再后一半再少 \(1\),所以总共少 \(\frac{n}{2} + \frac{n}{4} + ... = n\)),显然可以通过。
浙公网安备 33010602011771号