题意:每个点有点权,两点间的边权为两点点权的异或值,求最小生成树
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
int n,w[200005];
int nex[7000005][2];
int tot=0;
long long ans=0;
void ins(int x)
{
int now=0;
for(int i=29;i>=0;i--)
{
int t=(x>>i)&1;
if(nex[now][t]==0) nex[now][t]=++tot;
now=nex[now][t];
}
}
int query(int x)
{
int res=0,now=0;
for(int i=29;i>=0;i--)
{
int t=(x>>i)&1;
if(nex[now][t]) now=nex[now][t];
else now=nex[now][t^1],res=res|(1<<i);
}
return res;
}
void dfs(int l,int r,int deep)
{
if(deep==-1 || l>=r) return;
int mid=l-1;
while(mid<r && (w[mid+1]>>deep&1)==0 ) mid++;
dfs(l,mid,deep-1); dfs(mid+1,r,deep-1);
if(mid==l-1 || mid==r) return;
for(int i=l;i<=mid;i++) ins(w[i]);
int res=1e9;
for(int i=mid+1;i<=r;i++) res=min(res,query(w[i]));
ans+=res;
for(int i=0;i<=tot;i++) nex[i][0]=nex[i][1]=0;
tot=0;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
sort(w+1,w+n+1);
dfs(1,n,29);
printf("%lld\n",ans);
}