01字典树就是将数字转换为二进制(01)建树。通常用来求最大异或值问题。
建树:
void insert(int x)
{
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1; //取x的二进制的第i为与1按位与,都为1值才为1
if(trie[p][u]==0) //节点还没有建立
trie[p][u]=++id;
p=trie[p][u];
}
}
查找:
int find(int x)
{
int sum=0;
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(trie[p][!u]) //与u值不同的数存在,即让它俩进行异或,最后的值是最大的
{
p=trie[p][!u];
sum=sum*2+1; //有不相同的,
}
else
{
p=trie[p][u];
sum=sum*2; //没有不同的,sum一直*2,相当于二进制转换为十进制
}
}
return sum; //sum为最后的十进制值
}
if......else其中的语句相当于异或的过程,有不相同的异或为1,相同的为0.
例题:
在给定的 N 个整数 A1,A2……AN 中选出两个进行 xor(异或)运算,得到的结果最大是多少?
输入格式
第一行输入一个整数 N。
第二行输入 N 个整数 A1。
输出格式
输出一个整数表示答案。
数据范围
1≤N≤10^5,
0≤Ai<2^31
输入样例:
3
1 2 3
输出样例:
3
代码:
#include<bits/stdc++.h>
using namespace std;
int trie[31*101010][2];
int id;
int a[100009];
int find(int x)
{
int sum=0;
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(trie[p][!u])
{
p=trie[p][!u];
sum=sum*2+1;
}
else
{
p=trie[p][u];
sum=sum*2;
}
}
return sum;
}
void insert(int x)
{
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(trie[p][u]==0) //节点还没有建立
trie[p][u]=++id;
p=trie[p][u];
}
}
int main()
{
int n;
cin>>n;
int sum=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
insert(a[i]);
}
for(int i=0;i<n;i++)
{
sum=max(sum,find(a[i]));
}
cout<<sum<<endl;
return 0;
}