hdu4825 Xor Sum 字典树与异或(经典)

求某个数与一些数异或的最大值是字典树应用的一个经典问题。

主要思想是贪心,把数字都转化成二进制,把这些数按存到字典树中。从高位开始遍历,如果有不同的边(可以使得异或值为1)肯定走不同的边,如果没有则走与自己值相同的边(一定存在)。边走边统计,最后输出。


这道题题意是:输入一个数组,再给一些数字进行查询,问这些数字与数组中的哪个元素异或值最大。

思路:把输入的数组元素全部插入字典树,然后按照上面说的方法进行查询。


#include<stdio.h>
#include<string.h>
#include<algorithm>

using namespace std;

const int N = 3000000+5;
typedef long long LL;

struct Trie {
    int next[2];
    LL v;
    void init() {
        v = -1;
        memset(next, -1, sizeof(next));
    };
};

Trie trie[N];
int sz;

void init() {
    sz = 1;
    trie[0].init();
}

void myinsert(LL x) {
    int p = 0;
    for(int i = 32; i>= 0; i--) {
        int ch;
        if(x&(1ll<<i)) ch = 1;
        else ch = 0;
        if(trie[p].next[ch] == -1) {
            trie[p].next[ch] = sz;
            trie[sz++].init();
        }
        p = trie[p].next[ch];
    }
    trie[p].v = x;
}

LL query(LL q) {
    int p = 0;
    LL ret = 0;
    for(int i = 32; i >= 0; i--) {
        int ch = q&(1ll<<i)?1:0;
        if(trie[p].next[!ch] != -1) {
            ret |= (1ll<<i);
            p = trie[p].next[!ch];
        }
        else p = trie[p].next[ch];
    }
    return trie[p].v;
}

int main() {
    int t;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++) {
        init();
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) {
            LL x;
            scanf("%lld", &x);
            myinsert(x);
        }
        printf("Case #%d:\n", cas);
        while(m-- > 0) {
            LL q;
            scanf("%lld", &q);
            printf("%lld\n", query(q));
        }
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值