CSU 1216 異或最大值【字典樹】

Description

給定一些數,求這些數中兩個數的異或值最大的那個值

Input

第一行爲數字個數n,1 <= n <= 10 ^ 5。接下來n行每行一個32位有符號非負整數。

Output

任意兩數最大異或值

Sample Input

3
3
7
9

Sample Output

14


/*
    類型:字典樹+貪心
    分析:建一棵01字典樹,樹的深度就是整數的值的位數,然後根據異或的性質進行貪心
    吐槽:剛開始從低位向高位建樹,WA了幾次沒想出所以然,後面才發現,低位開始建樹的貪心策略是錯的
          因爲在查找的過程中從高位的路線轉移到低位的路線,最後前期貪心的結果沒高位的那麼多,心塞
*/

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int len = 31;
typedef struct Trie{
    Trie *next[2];
}Trie;
Trie root;
void createTrie(int x)
{
    Trie *p = &root, *q;
    for(int i=len;i>=0;i--){
        bool id = x&(1<<i);
        if(p->next[id] == NULL){
            q = (Trie *)malloc(sizeof(root));
            for(int j=0;j<2;j++)
                q->next[j] = NULL;
            p->next[id] = q;
            p = p->next[id];
        }
        else{
            p = p->next[id];
        }
    }
}
int findTrie(int x)
{
    int val=0;
    Trie *p = &root;
    for(int i=len;i>=0;i--){
        bool id = x&(1<<i);
        if(p->next[!id]!=NULL){
            val=val|(1<<i);
            p = p->next[!id];
        }
        else p = p->next[id];
    }
    return val;
}
void deal(Trie* T)
{
    for(int i=0;i<2;i++)
    {
        if(T->next[i]!=NULL)
            deal(T->next[i]);
    }
    free(T);
}
int main()
{
    //freopen("F:\\input.txt", "r", stdin);
    int n;
    while(~scanf("%d",&n)){
        int x,ans=0;
        for(int i=0;i<2;i++)root.next[i] = NULL;
        while(n--){
            scanf("%d",&x);
            createTrie(x);
            ans=max(ans,findTrie(x));
        }
        printf("%d\n",ans);
        for(int i=0;i<2;i++){
            if(root.next[i]!=NULL)
                deal(root.next[i]);
        }
    }
    return 0;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章