CF888G Xor-MST

Posted wxyww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF888G Xor-MST相关的知识,希望对你有一定的参考价值。

题目链接

problem

给出n个点,每个点有权值,求最小生成树。定义一条边的代价为所连接两点的权值异或值。

solution

考虑分治,根据最高位为0还是1分为两部分。然后分别求最小生成树。合并的时候就将最高位为0的一部分插入到trie中,然后从最高位为1的一部分中查询。

注意对trie的清空。

code

/*
* @Author: wxyww
* @Date:   2019-08-18 19:36:04
* @Last Modified time: 2019-08-18 20:20:03
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 200100,INF = 1e9;
ll read() 
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') 
        if(c=='-') f=-1;
        c=getchar();
    
    while(c>='0'&&c<='9') 
        x=x*10+c-'0';
        c=getchar();
    
    return x*f;

int tree[N * 31][2],a[N];
int n,tot;

int get(int x) 
    for(int i = 29;i >= 0;--i) printf("%d",x >> i & 1);
    puts("");

void add(int x) 
    // get(x);
    int p = 0;
    for(int i = 29;i >= 0;--i) 
        int k = x >> i & 1;
        if(!tree[p][k]) tree[p][k] = ++tot;
        p = tree[p][k];
    



int query(int x) 
    // get(x);
    int p = 0,ret = 0;
    for(int i = 29;i >= 0;--i) 
        int k = x >> i & 1;
        if(!tree[p][1] && !tree[p][0]) return INF;
        if(!tree[p][k]) 
            ret += 1 << i;
            p = tree[p][k ^ 1];
        
        else p = tree[p][k];
        
    
    // printf("%d\n",ret);
    return ret;

ll solve(int l,int r,int pos) 
    if(l > r) return 0;
    // printf("%d %d %d\n",l,r,pos);
    if(l == r || pos == -1) 
        add(a[l]);
        return 0;
    

    int mid = r;
    for(int i = l;i <= r;++i) 
        if(a[i] >> pos & 1) 
            mid = i - 1;break;
        
    


    ll ret = 0;
    ret += solve(l,mid,pos - 1);

    int mn = INF;

    for(int i = mid + 1;i <= r;++i) mn = min(mn,query(a[i]));

    if(mn != INF) ret += mn;

    for(int i = 0;i <= tot;++i) tree[i][0] = tree[i][1] = 0;
    tot = 0;

    ret += solve(mid + 1,r,pos - 1);

    // for(int i = mid + 1;i <= r;++i) add(a[i]);
    for(int i = l;i <= r;++i) add(a[i]);
    // printf("%d\n",ret);
    // printf("%d %d %d %d\n",l,r,pos,ret);
    return ret;


int main() 
    // freopen("1.in","r",stdin);
    n = read();
    for(int i = 1;i <= n;++i) a[i] = read();

    sort(a + 1,a + n + 1);

    // for(int i = 1;i <= n;++i) get(a[i]);

    // puts("");

    cout<<solve(1,n,29);

    return 0;

以上是关于CF888G Xor-MST的主要内容,如果未能解决你的问题,请参考以下文章

CF888G Xor-MST

[CF888G]Xor-MST

Codeforces 888G Xor-MST - 分治 - 贪心 - Trie

CodeForces - 888G Xor-MST(贪心+字典树+最小生成树)

CF888GXor-MST Trie树(模拟最小生成树)

$CF888G Xor-MST$ 最小生成树