2020牛客暑期多校训练营(第五场) Graph

本题和cf 888G是一样的

利用分治算法

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
const int maxn = 2e5+11;
typedef long long ll;

ll list[maxn];
ll tree[maxn*33][3];

int cnt=0;

ll add(ll x){//把数值插入字典树
    int root = 0;
    for(int i=29;i>=0;i--){
        int t = (x>>i)&1;
        if(!tree[root][t]) tree[root][t] = ++cnt;
        root = tree[root][t];//向下爬
    }
    return 0;
}

ll find(ll x){//查找字典树里面和x异或最小的数值
    int root = 0;
    ll an =0 ;
    for(int i= 29;i>=0;i--){
        ll t = (x>>i)&1;
        if(tree[root][t]) root = tree[root][t];
        else{
            root = tree[root][t^1];
            an |= (1<<i);
        }
    }
    return an;
}

ll ans = 0;

int dfs(int l,int r,int dep){
    if(dep==-1||l>=r) return 0;

    int mid = -100;
    for(int i = l;i<=r;i++){
        if((list[i]>>dep)&1) break;
        mid = i;
    }

    if(mid == -100 || mid == r){//全是1
        dfs(l,r,dep-1);
    }
    else{
        dfs(l,mid,dep-1);
        dfs(mid+1,r,dep-1);
    }

    if(mid==-100||mid==r) return 0;//dep位置全是0 或者全是1

    for(int i = l;i<=mid;i++){
        add(list[i]);
    }


    long long cns = 1e15;

    for(int i = mid+1;i<=r;i++){
        long long a = find(list[i]);
        cns = min(cns,a);
    }

    ans += 1LL*cns;
    
    for(int i=0;i<=cnt;i++){
        tree[i][0] = tree[i][1] = 0;
    }
    cnt = 0;
    return 0;
}
struct Node{
    int p;
    int len;
    Node(int aa,int bb):p(aa),len(bb){}
};

vector<Node>G[maxn];
void add(int x,int y,int len){
    G[x].push_back(Node(y,len));
}
int dfs2(int x,int fa,int dep){
    list[x] = dep;
    for(int i=0;i<G[x].size();i++){
        int p = G[x][i].p;
        int ln = G[x][i].len;
        if(p == fa) continue;
        dfs2(p,x,(dep^ln));
    }
    return 0;
}

int main(){
    ios::sync_with_stdio(false);
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y,len;
        scanf("%d%d%d",&x,&y,&len);
        x++;
        y++;
        add(x,y,len);
        add(y,x,len);
    }
    dfs2(1,-1,0);
    sort(list+1,list+1+n);
    ans = 0;
    dfs(1,n,29);
    printf("%lld
",ans);
    return 0;
}