Maximum AND

发布时间 2023-11-01 09:58:34作者: Zlc晨鑫

看到这么多位运算,拆位考虑。

对于\(f(a,b)\)的一位,要么是0,要么是1。

该位是1,说明有某种\(b\)的排列,使得该位上\(a_i \oplus b_i\)均为1。(因为\(\&\)的结果是1,说明全都是1)。

那么我们要优先满足哪一位为1呢?

一个直接的想法是优先满足高位为1,因为\(2^k > 2^{k-1}+2^{k-1}+...+2^1+2^0\),当前位如果可以为1,那么令它为1肯定严格优于让低位为1的任何方案(让低位为1的任何方案最大就是全都都是1,但是这也更小)。

然后发现有的位是无法为1的,只有a中0和1的个数刚好等于b中1和0的个数时,这一位才可能为1。

首先找到最高的可以为1的位\(k\),上面证明了,这样子的方案一定是最优解。

然后考虑后面的位,类似的,我们也尽量让每一位都为1。但是这样有一个问题:\(k\)位为1的约束,限制了\(a\)\(b\)之间的匹配。

一开始(求\(k\)的时候),\(a\)\(b\)可以任意匹配。

然后,\(a\)中所有第\(k\)位是0的可以和\(b\)中所有第\(k\)位是1的排列,\(a\)中所有第\(k\)位是1的可以和\(b\)中所有第\(k\)位是0的排列。也就是说,原集合分裂成了两个子集。直接对这两个子集操作,也是\(O(n)\)的。

类似的,每次对于一个可以排列的\(a,b\)的集合计算贡献之后,都会让它分成两个子集,为了保证复杂度严格\(O(n)\),要把空集特判掉。

具体实现可以记录下标。

CODE