最大异或对

最大异或对

给出n个数,第i个数为\(a_i\),问从中任意取两个数,进行异或运算,得到的结果的最大值,\(n\leq 10^5\)

首先暴力的思路是枚举每一个数,再确定另外一个数,现在问题是如何快速确定另外一个数。

二进制运算问题,采用二进制拆分,对每一位,尤其是从最高位考虑,尽可能选择一堆数,让最高位不为0,在从选出的一堆数再选一堆数,让次高位尽可能不为0,不停地缩小集合范围,就能得到我们的答案.

于是问题变成如何快速检索每一位对应的集合,这样我们就可以利用trie树来做了,因为它可以查询某一位一个字符对应的字符串,于是我们把数字看成01串,加入trie树,按照上面所说的思路即可,时间复杂度\(O(nlog(n))\)

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define Size 3100000
using namespace std;
int trie[Size][2],tot,
	a[100005];
il int ask(int);
il void insert(int),
	read(int&);
template<class free>
il free Max(free,free);
int main(){
	int n,ans(0);read(n);
	for(int i(1);i<=n;++i)
		read(a[i]),insert(a[i]);
	for(int i(1);i<=n;++i)
		ans=Max(ans,ask(a[i]));
	printf("%d",ans);
	return 0;
}
template<class free>
il free Max(free a,free b){
	return a>b?a:b;
}
il void read(int &x){
	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
il int ask(int x){int p(0),ans(0);
	for(int i(30);i>=0;--i)
		if(trie[p][x>>i&1^1])
			p=trie[p][x>>i&1^1],ans|=1<<i;
		else p=trie[p][x>>i&1];
	return ans;
}
il void insert(int x){int p(0);
	for(int i(30);i>=0;--i){
		if(!trie[p][x>>i&1])
			trie[p][x>>i&1]=++tot;
		p=trie[p][x>>i&1];
	}
}

posted @ 2019-07-26 08:07  a1b3c7d9  阅读(320)  评论(0编辑  收藏  举报