• D. Dr. Evil Underscores


    题意:今天,作为一个友谊礼物,Bakry给予Badawy n个整数a1,a2,...,an,让他去寻找一个数X,使得(underset{1 leq i leq n}{max} (a_i oplus X))最小。

    输入:
    第一行是一个整数n(1 <= n <= 10^5)
    第二行是n个整数a1,a2,...,an(0 <= ai <= 2^30 - 1)

    输出:
    (underset{1 leq i leq n}{max} (a_i oplus X))的最小值

    分析:对于异或最大值,我们可以采用字典树存储每个整数的01串,如果我们要去找一个数X,去查询和每个数的异或最大值,然后比较所有的异或最大值,枚举所有的x,这样会导致超时。我们可以去寻找一种更加棒的方法,当我们去遍历一颗trie树的时候,从高往低遍历每一位,每个结点都有1~2个分支,如果只有一个分支,我们用x异或的时候,我们贪心地希望x这位和这个结点的值相等,这样,我们所能得到的异或最大值会最小,如果有两个分支怎么办,我们去递归求解这两个分支,取一个min,就能得到最小值,同时,我们可以发现,我们可以在递归的时候,顺便把这个最大值求解出来,当只有一个分支的时候,意味着我们要去选择一个x,它的这位是和这个分支的位相等,意味着值为0,如果有两个分支,因为我们求解的是最大值,所以,我们会加上1 << k,这样,我们就可以得到最大值最小了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <algorithm>
     
    using namespace std;
    using LL = long long;
    const int N = 3200005;
    const int M = 100005;
     
    int trie[N][2], idx;
    int a[M];
     
    void insert(int x)
    {
    	int p = 0;
    	for (int i = 29; i >= 0; --i)
    	{
    		int u = x >> i & 1;
    		if (!trie[p][u]) trie[p][u] = ++idx;
    		p = trie[p][u];
    	}
    }
     
    int solve(int cur, int k)
    {
    	if (k == -1)
    		return 0;
    	if (trie[cur][0] == 0)
    		return solve(trie[cur][1], k - 1);
    	else if (trie[cur][1] == 0)
    		return solve(trie[cur][0], k - 1);
    	else
    	{
    		return (1 << k) + min(solve(trie[cur][1], k - 1), solve(trie[cur][0], k - 1));
    	}
     
    }
     
    int main()
    {
    	int n;
    	scanf("%d", &n);
     
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d", &a[i]);
    		insert(a[i]);
    	}
     
    	int ans = solve(0, 29);
     
    	cout << ans << endl;
    		
    	return 0;
    }
    
    
  • 相关阅读:
    Nginx日志管理
    Nginx负载均衡
    Nginx 缓存
    Nginx代理服务器
    Nginx搭建 Web服务
    Nginx HTTP模块
    洛谷P1012拼数
    洛谷 P1876 开灯
    洛谷P2084 进制转化
    关于typedef的用法
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12207024.html
Copyright © 2020-2023  润新知