01字典树,贪心-CF1285D

题目大意:给你n( n ≤ 1 e 5 n\leq1e5 n1e5)个整数.让你确定一个整数X最小化 max ⁡ { a i ⊕ X } \max\{a_i\oplus X\} max{ aiX}

题目思路:

二进制从高位到低位考虑.当第 i i i位同时存在’0’和’1’时,贡献恒为 2 i 2^{i} 2i.这一位放0/1就只需要考虑另一半的值了.

例如:X的第 i i i位放0.那么那些 [本位为0的数]与x作异或都会比 [本位为1的数]与x作异或 要小了.所以接下来我们只需要考虑那些 [本位为1的数].反之亦然.所以这里形成两个不同的决策(要么填1要么填0嘛).我们可以递归求解,然后取两者的最小值即可.

然后当本位只存在’0’ 或 只存在’1’ 时,X填相同的值,贡献就为0了.

所以用01Trie存储序列.dfs跑一下求答案即可.

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 4e6;
namespace Trie{
    
    
    int tr[maxn][2] , v[maxn] , tot;
    void add (int x){
    
    
        int u = 0;v[u]++;
        for (int i = 30 ; i >= 0 ; i--){
    
    
            int g = ((x >> i) & 1);
            if (!tr[u][g]) tr[u][g] = ++tot;
            u = tr[u][g];
            v[u]++;
        }
    }
    ll dfs (int u , int pos)
    {
    
    
        if (pos == -1) return 0;
        if (tr[u][0] && tr[u][1]) return min (dfs(tr[u][0] , pos - 1) , dfs(tr[u][1] , pos - 1)) + (1ll << pos);
        if (tr[u][0]) return dfs (tr[u][0] , pos - 1);
        return dfs (tr[u][1] , pos - 1);
    }
}
int main()
{
    
    
    ios::sync_with_stdio(false);
    int n; cin >> n;
    for (int i = 1; i <= n ; i++){
    
    
        int x;cin >> x; Trie::add(x);
    }
    cout << Trie::dfs (0 , 30) << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35577488/article/details/109075516