CSU 1216 异或最大值 01trie

来源:互联网 发布:java摆脱内存泄露 编辑:程序博客网 时间:2024/05/18 17:59

题目:

https://vjudge.net/problem/CSU-1216

题意:

给定一些数,求这些数中两个数的异或值最大的那个值

Input
多组数据。第一行为数字个数n,1 <= n <= 10 ^ 5。接下来n行每行一个32位有符号非负整数。

Output
任意两数最大异或值

思路:

最暴力的方法是枚举两个数,这样显然不可行,当枚举x时,怎么找到另一个数字y使得xy最大呢?可以发现,应该是分解成二进制然后从最高位开始对比,其中有一些数字和x在当前位上是相同的,另外一些是不同的,这时候我们应该对数字进行选择,显然应该选取不同的,相同的都扔掉,然后往下一位对比,当然如果全相同的话,就不能扔了,也往下一位对比,一直到末尾。我们可以用字典树实现这个选择功能,这样就比较简单了

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 100000 + 10, M = 2;struct node{    node *next[M];    void init()    {        memset(next, 0, sizeof next);    }}trie[N*25], *root;int tot;int len = 31;int a[N];node* new_node(){    trie[tot].init();    return trie + tot++;}void trie_init(){    tot = 0;    root = new_node();}void trie_insert(int val){    node *p = root;    for(int i = len-1; i >= 0; i--)    {        int j = 1 & (val>>i);        if(p->next[j] == NULL) p->next[j] = new_node();        p = p->next[j];    }}int trie_query(int val){    node *p = root;    int ans = 0;    for(int i = len-1; i >= 0; i--)    {        int j = ! (1 & (val>>i));//j是val在当前位置上的相反数,即val在当前位是0,则j=1,否则反之        if(p->next[j] != NULL)//相反数存在,则异或后当前位的二进制为1        {            p = p->next[j];            ans = ans * 2 + 1;        }        else //否则为0        {            p = p->next[!j];            ans = ans * 2 + 0;        }    }    return ans;}int main(){    int n;    while(~ scanf("%d", &n))    {        trie_init();        int ans = 0;        for(int i = 1; i <= n; i++)        {            scanf("%d", &a[i]);            trie_insert(a[i]);            ans = max(ans, trie_query(a[i]));        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击