我尝试过用struct指针表示树 和 用数组表示树两种方式,前者爆内存,后者顺利ac,这差距够明显了吧
用指针表示树
using namespace std;
#include<vector>
#include<iostream>
struct btree{
vector<btree*> ne;
btree():ne(2, nullptr){};
};
int main(){
btree* root = new btree();
int n;
cin>>n;
int T = n;
vector<int> d;
while(T--){
int tmp;
cin>>tmp;
d.push_back(tmp);
btree* p = root;
for(int i = 30;i >= 0;i--){
int x = tmp >> i & 1;
if(p->ne[x] == nullptr){
p->ne[x] = new btree();
}
p = p->ne[x];
}
}
long long ans = 0;
//遍历每个值,查看是否有更大的
for(int i = 0;i < n;i++){
int val = d[i];
btree* p = root;
long long res = 0;
for(int j = 30;j >= 0;j--){
int x = val >> j & 1;
if(p->ne[1 - x] != nullptr){
p = p->ne[1 - x];
res += 1 << j;
}
else p = p->ne[x];
}
ans = max(ans, res);
}
cout<<ans;
return 0;
}
用数组模拟树
using namespace std;
#include<vector>
#include<iostream>
const int N = 100010, M = 3100010; //M表示结点个数,因为每个数最大值为2^31 - 1,需要30个结点可以表示,总共有 <=N 个数,故 M = 30 * N = 3100010;
int n;
int son[M][2], idx;//用idx表示结点的id
//这里和前面的ne[idx] = idx类似,不过字典树与普通树的区别在于,字典树的值不需要单独存储,而是通过树的遍历推断出
void insert(int val){
//最多右移31个位置
int p = 0;//表示根节点
for(int i = 30; i >= 0; i--){
int x = val >> i & 1;
if(!son[p][x])son[p][x] = ++idx;//当前结点不存在,需要添加结点
p = son[p][x];
}
}
//查询与x异或值最大的结点
int search(int val){
int p = 0, res = 0;
for(int i = 30; i >= 0; i--){
int x = val >> i & 1;
if(son[p][!x]){
res += 1 << i;
p = son[p][!x];
}
else p = son[p][x];
}
return res;
}
int main(){
int n;
cin>>n;
vector<int> d(n);
for(int i = 0;i < n;i++){
cin>>d[i];
insert(d[i]);
}
int ans = 0;
for(int i = 0;i < n;i++)ans = max(ans, search(d[i]));
cout<<ans;
return 0;
}