您的位置:首页 > 其它

Codeforces 888G XOR MST(分治)

2017-11-12 20:53 387 查看

题目链接

Codeforces 888G XOR MST(分治)

分析

 这是很经典的问题,可以分治.

 从最高位开始考虑,这些点一定分成两组,一组最高位为1,另外一组为0,两组之间选一条最小的边就行了,这个过程一可以分治,具体看代码,写的很详细

AC code

#include <bits/stdc++.h>
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<<dep,cmp_bit)-a;}

LL connect(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 ; i<n ; ++i)scanf("%d",a+i );
sort(a,a+n);
printf("%lld\n",solve(29,0,n));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces