zoukankan      html  css  js  c++  java
  • CF 1446 C-Xor Tree

    题目链接:https://codeforces.com/contest/1446/problem/C
    思路
    一个数字选择异或最小的,对于当前位,一定选择数字相同的,例如3的第一位为000000000000000011,那么第一位尽可能地选择0.
    可以注意到从高位到低位,如果一个位上既有0又有1,那么该位为0的都和0在一个连通块内,1和1都在一个连通块内,因此同位相同地一定在一个联通块内,特殊情况就是当前位只有一个0或者一个1,必须选择这一位不同的,所以可以保留只有一个0或一个1的情况。那一位全0或者全1那么就是完美的情况。
    那么就把所有的数先插入到字典树上,然后暴力考虑对于第i位是保留1还是保留0,dfs一下即可。
    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    const int N = 2e5 * 29 + 10, M = 2e5 + 10;
    int a[M], cnt[N];
    int tr[N][2], idx, res;
    
    void insert(int x) {
        int p = 0;
        for(int i = 29; i >= 0; i--) {
            int id = (x >> i) & 1;
            if(!tr[p][id]) {
                tr[p][id] = ++idx;
                memset(tr[idx], 0, sizeof tr[idx]);
                cnt[idx] = 0;
            }
            p = tr[p][id];
            cnt[p]++;
        }
    }
    
    void dfs(int p, int sum) {
        if(!tr[p][0] && !tr[p][1]) {
            res = min(res, sum);
            return;
        }
    //    cout << p << " " << sum << endl;
    
        if(tr[p][1]) {
            int num = max(cnt[tr[p][0]] - 1, 0);
            dfs(tr[p][1], sum + num);
        }
        if(tr[p][0]) {
            int num = max(cnt[tr[p][1]] - 1, 0);
            dfs(tr[p][0], sum + num);
        }
    }
    
    void solve() {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            insert(a[i]);
        }
        res = 1e9;
        dfs(0, 0);
        printf("%d
    ", res);
    }
    
    int main() {
    //    freopen("in.txt", "r", stdin);
        solve();
        return 0;
    }
    
  • 相关阅读:
    安装win7 ubuntu双系统
    idea maven打jar包
    mongodb入门
    mongodb备份与恢复
    使用cmd时cd命令失效
    vue 项目中使用阿里巴巴矢量图标库iconfont
    vue img标签用法
    vue 点击当前元素改变样式
    vue 路由跳转传参
    iview table绑定双击事件
  • 原文地址:https://www.cnblogs.com/ZX-GO/p/14412985.html
Copyright © 2011-2022 走看看