梦熊四月 csp-s 模拟赛2 T2 排序
小 B 想要对一个长为 \(n\) 的序列 \(A\) 排序。已知 \(A\) 中只包含 \(0,1,\cdots,n-1\) 且对任意 \(i\ne j\) 有 \(A_i\ne A_j\) 且 \(n\) 为 \(2\) 的次幂。
为了排序,小 B 只想用以下两种操作:
交换相邻的两个位置,也就是说选择 \(1\le i\le n-1\) 并且交换 \(A_i,A_{i+1}\) 。
选择一个整数 \(x\),将每个 \(A_i\) 都替换为 \(A_i\oplus x\) ,这里 \(\oplus\) 为二进制按位异或操作。
请问最少需要多少次操作才能给整个序列排序?
\(n\le 2^{22}\)。时间限制 3s。
很好的题,考察了推性质的能力。
不难发现二操作最多进行 \(1\) 次,因为异或具有结合律。
现在重点来研究一下二操作。
令 \(n=2^k\),显然 \(x\le n\),根据 \(p\ne q\) 时 \(p\oplus x\ne q\oplus x\),发现异或后的序列是原序列的一个置换。注意,当 \(n\) 不为 \(2\) 的次幂时这一点是不满足的,\(n=2^k\) 保证了映射的定义域和值域相同。
因此最优的方法一定是通过异或 \(x\) 后得到原序列的一个置换,然后反复应用操作 \(1\),所以再来看看操作 \(1\)。
结论:操作 \(1\) 最少需要应用 \(s(A)\) 次,\(s(A)\) 代表 \(\{A_i\}\) 的逆序对数。
证明可以看 火柴排队。
所以我们只需要找到 \(x\),使得 \(\{A_i\oplus x\}\) 的逆序对数最小即可。
这个数据范围明示 \(O(n\log n)\),拆位考虑。
如果 \(x\) 的第 \(i\) 位为 \(1\),当且仅当 \(\{A_i\oplus 2^i\}\) 的逆序对数有所减少。
证明
首先我们来证明对于两个数 \(A_i,A_j\),两者在数组中的相对位置只会至多发生一次改变。
不失一般性地令 \(A_i<A_j\)。设两数的二进制下最高的出现不同的是第 \(p\) 位。
显然 \(x\) 二进制下的 \(p+1\sim\infty\) 位我们都不关心,现在来讨论 \(x\) 二进制下第 \(p\) 位的数。
-
若 \(x(p)=1\),此时由于 \(A_i(p)\ne A_j(p)\),所以两者可能会产生相对位置的交换,不难发现,此后无论 \(x(0)\sim x(p-1)\) 取何值都不会产生第二次交换。
-
否则 \(x(p)=0\),同样,无论 \(x(0)\sim x(p-1)\) 的取值,都不会产生交换。
由于 \(A_i,A_j\) 的相对位置只与 \(x(p)\) 有关,所以可以认为 \(x\) 在二进制下各位取值对答案的贡献,每一位都是不相关的、独立的。
因此,可以按照上面所说的贪心。
怎么统计逆序对数是否减少?
假设我们目前在考虑 \(x\) 的第 \(p\) 位,那么两个数的相对位置可能改变当且仅当对于 \(q>p\),\(A_i(q)=A_j(q)\),于是我们就可以利用这个性质,方便快捷的统计出对于一个数来说,它的新逆序对数会是多少。
当然,本文中的所有证明都不是那么的严谨,严谨的证明需要群论知识。