Codeforces 888G XOR MST(分治)

题目链接

Codeforces 888G XOR MST(分治)

分析

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

AC code

#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;
}

你可能感兴趣的:(算法刷题)