CF1285D Dr. Evil Underscores 题解

给定一个序列 \(a\),选取一个 \(x\),使 \(\max_{i=1}^na_i\oplus x\) 最小。

看到这种题直接按位考虑,如果最高位全是 \(1\) 那把 \(x\) 的这位全变成 \(1\),如果最高位全是 \(0\) 那把 \(x\) 的这位全变成 \(0\)。如果有 \(0\)\(1\)\(x\) 的这一位不管怎么取 \(\max_{i=1}^na_i\oplus x\) 都要算上 \(2^k\),对于下一位就按照这位取 \(0\) 还是 \(1\) 去分治,取较小的就行了。因为最多递归 \(\log w\) 次,每层需要 \(\mathcal O(n)\),所以复杂度是 \(\mathcal O(n\log w)\)

//不向焦虑与抑郁投降,这个世界终会有我们存在的地方。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using std::cin;using std::cout;
using std::max;using std::min;
using bsi=std::basic_string<int>;
constexpr int N=1e5+1;
int solve(const bsi &a,int k){
	if(a.empty()||k<0)return 0;
	bsi b1,b2;
	for(int i:a)(i>>k&1?b1:b2)+=i;
	if(b1.empty())return solve(b2,k-1);
	if(b2.empty())return solve(b1,k-1);
	return 1<<k|min(solve(b1,k-1),solve(b2,k-1));
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	std::ios::sync_with_stdio(false);cin.tie(nullptr);
	int n;bsi a;
	cin>>n;a.resize(n);
	for(int&i:a)cin>>i;
	cout<<solve(a,29);
	return 0;
}

关于 basic_stringvectorbasic_string 的各种操作更快,但是空间消耗是 \(32\),而 vector 只需要 \(24\)

posted @ 2022-11-09 17:43  蒟酱  阅读(30)  评论(0编辑  收藏  举报