AcWing143-https://www.acwing.com/problem/content/145/
题大意:给出N个数,所有数小于2^31, N <= 1e5 求其中异或结果最大的数对
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int trie[33*maxn][2];
int tot = 1;
void insert(int a){
int k = 30, p = 1;
for(; k >= 0; k--){
if(!trie[p][a>>k&1]) trie[p][a>>k&1] = ++tot;
p = trie[p][a>>k&1];
}
}
int search(int a){
int res = 0, p = 1;
for(int k = 30; k >= 0; k--){
int tk = a>>k&1;
if(trie[p][!tk]) p = trie[p][!tk], res = res*2 + 1;
else p = trie[p][tk], res *= 2;
}
return res;
}
int a[maxn];
int ans;
int main(){
int n;
ios::sync_with_stdio(false), cin.tie(0);
cin>>n;
for(int i = 1; i <= n; i++){
cin>>a[i];
insert(a[i]);
}
for(int i = 1; i <= n; i++)
ans = max(ans, search(a[i]));
cout<<ans;
return 0;
}
Trie的很有趣的应用-存储数字的二进制码
再借由Xor的性质-在字典树搜索和当前数字二进制码相反项尽可能多的二进制数(从第32位开始搜起,保证算法正确性)
将朴素O(n^2)的算法降低到了O(n)级别上。
发散一下-牵扯二进制运算的题并且数据范围允许使用字典树的情况下,都可以考虑Trie。
-再胡思乱想一下的话……
Trie降低复杂度的原因是因为将原来一个计算一个数字的最大异或对需要扫描整个序列
而现在通过存储到Trie中,O(n)的预处理将所有数字的扫描时间降低到了O(1)
数字-二进制串-一定的匹配规则/也即在Trie中的搜索规则(本题中按Xor匹配,即各个位上从高到低尽量不相同)-Trie树