题目链接:传送门
描述
在给定的 $N$ 个整数 $A_1, A_2,cdots,A_N$ 中选出两个进行xor运算,得到的结果最大是多少?
输入格式
第一行一个整数 $N$,第二行 $N$ 个整数 $A_1, A_2,cdots,A_N$。
输出格式
一个整数表示答案。
样例输入
3
1 2 3
样例输出
3
数据范围与约定
对于100%的数据:$N le 10^5, 0 le A_i < 2^{31}$。
题解:
由于 $0 le A_i < 2^{31}$,即二进制下最小是 $31$ 个 $0$,最大是 $31$ 个 $1$。将输入 $A_i$ 全部转化成长度为 $31$ 的 $0,1$ 字符串 $S_i$。
以最高位为字符串头,插入字典树。每次插入 $S_i$ 后,都在字典树中按贪心思路,尽可能找与 $S_i$ 相异的儿子节点(比如 $S_i$ 当前位为 $0$,那么我尽量找 $1$ 那个儿子,如果没有再找 $0$ 这个儿子)。
这样一来,每次插入 $S_i$ 后,都能找出 $A_1 sim A_i$ 每个与 $A_i$ 异或的结果之中最大的。
那么,当 $A_1, A_2,cdots,A_N$ 全部插入后,我就已经查找完所有满足 $i le j$ 的 $A_i$XOR$A_j$,维护最大值即可。
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; namespace Trie { const int SIZE=maxn*32; int sz; struct TrieNode { int ed; int nxt[2]; }trie[SIZE]; void init() { sz=1; memset(trie,0,sizeof(trie)); } void insert(int x) { int p=1; for(int k=30;k>=0;k--) { int ch=(x>>k)&1; if(trie[p].nxt[ch]==0) trie[p].nxt[ch]=++sz; p=trie[p].nxt[ch]; } } int MaxXor(int x) { int res=0; int p=1; for(int k=30;k>=0;k--) { int ch=(x>>k)&1; if(trie[p].nxt[ch^1]) { p=trie[p].nxt[ch^1]; res|=1<<k; } else p=trie[p].nxt[ch]; } return res; } }; int n; int main() { cin>>n; Trie::init(); int ans=0; for(int i=1,x;i<=n;i++) { cin>>x; Trie::insert(x); ans=max(ans,Trie::MaxXor(x)); } cout<<ans<<endl; }