询问所给数与数组中所有数亦或的最大值

本文介绍了一种利用Trie树解决在给定数组中找到与目标数进行异或操作能得到最大结果的算法。通过构建Trie树,对每个输入数进行反向查找,确定目标数的每一位是1还是0来得到最大异或值。这种方法在处理大规模数据时,相比暴力求解,能有效提高效率至O(nlog32)。
摘要由CSDN通过智能技术生成
// 11-4询问所给数与数组中所有数亦或的最大值,O(nlog32) 
// 思路:构造Trie树,询问数取反后,若能在Trie树找到对应的则该位为1,否则为0 
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 500000;
unsigned int x[MAXN + 10];  // 最多是2^32 

struct Trie {
    vector<Trie*> child;
    Trie(): child(vector<Trie*>(2, NULL)) {}  // 初始化子节点为Null 
};

// 增加Trie树的节点 
void add(int x, Trie* root) {
    for (int i = 31; i >= 0; --i) {  // 从最高位开始遍历
        int bit = (x >> i) & 1;  // bit=1最高位1,bit=0最高位0 
    	// 如果没有对应的子节点,则新建 
        if (!root->child[bit]) root->child[bit] = new Trie(); 
        root = root->child[bit];  // 更新根节点 
    }
}

// 反向寻找符合的数,找到为1否则为0 
unsigned int search(int x, Trie* root) {
    unsigned int ans = 0;
    for (int i = 31; i >= 0; --i) {  // 从最高位开始比 
        bool bit = (x >> i) & 1;  // bit=1最高位1,bit=0最高位0 
        ans = ans << 1; 
        if (root->child[!bit]) {
        	ans++;  // 如果存在匹配的点,则答案位+1 
        	root = root->child[!bit];  // 同时顺着该点继续往下走 
		} 
        else root = root->child[bit];  // 不存在匹配的点,更新根节点
    }    
    return ans;
}

int main() {
    Trie *root = new Trie();
	int n, q;
    scanf("%d%d", &n, &q);
    // 创建Trie树,O(n) 
    for (int i = 1; i <= n; i++) { 
		scanf("%u", x + i);
		add(x[i], root); 
	} 
	// 查询对应的数 
    while (q--) {
    	unsigned int ans = 0;
        unsigned int y;
        scanf("%u", &y);
        for (int i = 1; i <= n; i++)
			ans = search(y, root);  // Trie(20分,超时) 
			// ans = max(ans, x[i] ^ y);  // 暴力解法(60分,超时) 
        printf("%u\n", ans);
    }
    return 0;
}

/*
Input
4 2
1 2 3 4
5
1
Output
7
5
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值