最小生成树,但是边太多了,不好写
但是如果按照最高位1来分类成个集合
集合内部连边肯定比较优秀
集合与集合之间连一条边构成树就好了
连哪条边呢?可以采用字典树来完成
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e7+10;
int n,zi[maxn][2],id,a[maxn];
long long ans;
void insert(int x)
{
int now=0;
for(int i=30;i>=0;i--)
{
int t = (x>>i)&1;
if( !zi[now][t] ) zi[now][t]=++id;
now = zi[now][t];
}
}
int ask(int x)
{
int now=0,ans=0;
for(int i=30;i>=0;i--)
{
int t = ((x>>i)&1);
if( zi[now][t] ) now = zi[now][t];
else now = zi[now][t^1],ans+=(1<<i);
}
return ans;
}
void dfs(int l,int r,int dep)
{
if( dep==-1||l>=r ) return;
int mid = l;
while( mid<=r&&((a[mid]>>dep)&1)==0 ) mid++;
mid--;
dfs(l,mid,dep-1);
dfs(mid+1,r,dep-1);
if( mid==l-1||mid==r ) return;
for(int i=l;i<=mid;i++) insert(a[i]);
long long temp = 1e18;
for(int i=mid+1;i<=r;i++)
temp = min( temp,(long long)ask(a[i]) );
ans+=temp;
for(int i=0;i<=id;i++) zi[i][0]=zi[i][1]=0;
id=0;
}
signed main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
sort(a+1,a+1+n);
dfs(1,n,30);
printf("%lld",ans);
} 
京公网安备 11010502036488号