CF 1446C-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\n", res);
}

int main() {
//    freopen("in.txt", "r", stdin);
    solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值