World Tour Finals 2022 Day2 E: Adjacent Xor Game
考虑从高到低位做,不断贪心的一个过程。即假设把当前所有数 \(a_i\) 看成 \(\lfloor \frac{a_i}{2^d} \rfloor\),有当前最优答案 \(ans_d\);现在把所有数看成 \(\lfloor \frac{a_i}{2^{d-1}} \rfloor\),推出下一步的答案 \(ans_{d-1}\)。
假设 \(/2^d\) 时,每一步 xor 完的序列是 \(a_1,a_2,..,a_m\),其中 \(a_i < a_{i+1}\) 且 \(a_m=ans_d\)(这里忽略了所有 \(=0\) 的数)。从 \(d\to d-1\) 时,现在每个 xor 的数会变为 \(2x\) 或 \(2x+1\),并且会加入一堆 \(1\)。
如果没有新加入的 1,那么显然 \(ans_{d-1} = ans_d\times 2\)。发现新加入的一堆 1 对序列很有影响,因为它们只能被插在“空位”里,如果“空位”不足就会不得不增加 \(ans_{d-1}\)。
据此可以写出一份暴力,计算一个数组 \(a\) 的答案:
int wk(vi o){
n=o.size();For(i,1,n)a[i]=o[i-1],vis[i]=0;
int now=0,res=0;
Rep(i,30,0){
int cnt=0,cnt2=now;
For(j,1,n){
if(!vis[j] && (a[j]>>i&1)) ++cnt,vis[j]=1;
else if(vis[j] && (a[j]>>i&1)) ++cnt2;
}
if(cnt<=cnt2) now+=(cnt2-cnt),res=res*2;
else if(cnt<=cnt2+1) res=res*2+1;
else {
cnt-=(cnt2+1);
now+=cnt;
res+=cnt;
res*=2;
res+=1;
}
// cout<<"res "<<i<<" "<<res<<" "<<now<<"\n";
}
return res;
}