Codeforces 888G XOR MST(分治)
这是很经典的问题,可以分治.
从最高位开始考虑,这些点一定分成两组,一组最高位为1,另外一组为0,两组之间选一条最小的边就行了,这个过程一可以分治,具体看代码,写的很详细
#include
using namespace std;
#define ms(x,v) (memset((x),(v),sizeof(x)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define INF64 0x3f3f3f3f3f3f3f3f
typedef long long LL;
typedef pair<int,int > Pair;
const int maxn = 2e5+10;
int a[maxn];
inline bool cmp_bit(int x,int y){return !!(x&y);}
inline int MID(int l,int r,int dep){return upper_bound(a+l,a+r,1<int dep,int l1,int r1,int l2,int r2){
if(l1==r1 || l2 == r2)return INF64;
if(a[l1] == a[r1-1] && a[l2] == a[r2-1])return a[l1] ^ a[l2];
int mid1 = MID(l1,r1,dep),mid2 = MID(l2,r2,dep);
if((mid1 == r1 && mid2==l2) ||(mid1==l1 && mid2==r2) || (mid1==r1 && mid2==r2)||(mid1==l1 && mid2==l2) )//左右全0或全1
return connect(dep-1,l1,r1,l2,r2);
else return min(connect(dep-1,l1,mid1,l2,mid2),connect(dep-1,mid1,r1,mid2,r2));//全0的里选一条边,或者全1的选一条边
}
LL solve(int dep,int l,int r){
if(!dep)return (a[l] ^a[r-1]) &1;
int mid= MID(l,r,dep);
if(mid==l || mid == r)//全0或全1
return solve(dep-1,l,r);
else return connect(dep-1,l,mid,mid,r) + solve(dep-1,l,mid)+solve(dep-1,mid,r);
}
int main(int argc, char const *argv[]) {
int n;
scanf("%d",&n );
for(int i=0 ; iscanf("%d",a+i );
sort(a,a+n);
printf("%lld\n",solve(29,0,n));
return 0;
}