Original title: http://codeforces.com/contest/888/problem/G
Meaning of the questions:
2e5 given point, the right side of the right or outliers, minimum spanning tree.
Resolution:
The so-called Boruvka's algorithm , that is, only if the two sets, so I'm sure the right choice for a minimum of side edge connects two sets.
Here are just apply a similar idea.
For the value of each point in binary build the Trie.
In the second layer, for example, the left point is (
), the right (
). If the point is connected to the left point to the right, then the right side will contain (
) In this section, the value is very large, so you can draw emotional: a collection of left and right set of connected only by an edge.
And all connection sets down to do just a recursive subset can be.
This edge derived: through all points to the left, to the right to find a minimum XOR up, and then to take min.
XOR together to find the smallest is also very easy, direct from top to bottom can be greedy.
note: an array of open 4e6 will TLE
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int maxn=8e6+9;
int a[maxn],l[maxn],r[maxn],son[maxn][2],num;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
if(c==EOF){
x=-1;
return ;
}
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
void insert(int pos){
int rt=0;
for(int i=29;i>=0;i--){
int to=(a[pos]>>i)&1;
if(!son[rt][to])son[rt][to]=++num,l[num]=r[num]=pos;
rt=son[rt][to];
l[rt]=min(l[rt],pos),
r[rt]=max(r[rt],pos);
}
}
LL fin(int val,int rt,int dep){
if(dep==0||l[rt]==r[rt]) return (LL)a[l[rt]];
int to=1&(val>>dep-1);
if(son[rt][to])return fin(val,son[rt][to],dep-1);
else if(son[rt][!to]) return fin(val,son[rt][!to],dep-1);
else return 0;
}
LL ans=0;
void dfs(int rt,int dep){
if(dep==0)return ;
int ls=son[rt][0],rs=son[rt][1];
if(ls&&rs){
LL res=2e18;
for(int i=l[ls];i<=r[ls];i++){
res=min(res,a[i]^fin(a[i],rs,dep-1));
}
ans+=res;
}
if(ls)dfs(ls,dep-1);
if(rs)dfs(rs,dep-1);
}
int main(){
int n;read(n);
for(int i=1;i<=n;i++)read(a[i]);
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)insert(i);
dfs(0,30);
printf("%lld\n",ans);
}