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

来源:互联网 发布:窗帘销售软件 编辑:程序博客网 时间:2024/06/05 19:38

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

主要思想是贪心,把数字都转化成二进制,把这些数按存到字典树中。从高位开始遍历,如果有不同的边(可以使得异或值为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;}


0 0
原创粉丝点击