1. 程式人生 > >HDU4825Xor Sum字典樹+異或 建樹

HDU4825Xor Sum字典樹+異或 建樹

http://acm.hdu.edu.cn/showproblem.php?pid=4825

Problem Description

Zeus 和 Prometheus 做了一個遊戲,Prometheus 給 Zeus 一個集合,集合中包含了N個正整數,隨後 Prometheus 將向 Zeus 發起M次詢問,每次詢問中包含一個正整數 S ,之後 Zeus 需要在集合當中找出一個正整數 K ,使得 K 與 S 的異或結果最大。Prometheus 為了讓 Zeus 看到人類的偉大,隨即同意 Zeus 可以向人類求助。你能證明人類的智慧麼?

 

 

Input

輸入包含若干組測試資料,每組測試資料包含若干行。
輸入的第一行是一個整數T(T < 10),表示共有T組資料。
每組資料的第一行輸入兩個正整數N,M(<1=N,M<=100000),接下來一行,包含N個正整數,代表 Zeus 的獲得的集合,之後M行,每行一個正整數S,代表 Prometheus 詢問的正整數。所有正整數均不超過2^32。

 

 

Output

對於每組資料,首先需要輸出單獨一行”Case #?:”,其中問號處應填入當前的資料組數,組數從1開始計算。
對於每個詢問,輸出一個正整數K,使得K與S異或值最大。

 

 

Sample Input

 

2 3 2 3 4 5 1 5 4 1 4 6 5 6 3

 

 

Sample Output

 

Case #1: 4 3 Case #2: 4

 

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstdlib>
#define N 100010
using namespace std;
int n,k,m;
char s[40];
int a[N];
struct Trie
{
    int id;//id是後來為了輸出對應的數而設定的變數!
    struct Trie *Next[2];
    Trie()
    {
        id=0;
        for(int i=0; i<2; i++)
            Next[i]=NULL;
    }
};
void Trie_Inser(Trie *p,char s[],int id)
{
    int i=0;
    Trie *q=p;
    while(i<=32)
    {
        int nx=s[i]-'0';
        if(q->Next[nx]==NULL)
        {
            q->Next[nx]=new Trie;
        }
        q=q->Next[nx];
        i++;
    }
    q->id=id;
}
int Trie_Serch(Trie *p,char s[])
{
    int i=0;
    Trie *q=p;
    while(i<=32)
    {
        int nx=s[i]-'0';
        if(q->Next[nx]==NULL)nx^=1;//nx進行異或轉變;
        //特別特別注意的是某個節點往下之後可能會出現空節點;
        //這樣只能取存在的節點繼續往下了,所以nx^=1,就相當於x取反,相對於01;
        q=q->Next[nx];//q轉移;
        i++;
    }
    return q->id;//返回位置!
}
int main()
{
    int t;
    cin>>t;
    int ca=1;
    while(t--)
    {
        scanf("%d%d",&n,&m);
        int x;
        Trie *p=new Trie;//建立根樹;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            a[i]=x;
            for(int i=0; i<40; i++)s[i]='0';
            int l=32;
            while(x)
            {
                if(x&1)
                {
                    s[l]='1';
                }
                x>>=1;
                l--;
            }
            Trie_Inser(p,s,i);//分解成二進位制插入字典樹;
        }
        printf("Case #%d:\n",ca++);
        while(m--)
        {
            scanf("%d",&x);
            for(int i=0; i<40; i++)s[i]='1';
            int l=32;
            while(x)
            {
                if(x&1)
                {
                    s[l]='0';//將被查詢的數二進位制取反,查詢
                }
                x>>=1;
                l--;
            }
            int id=Trie_Serch(p,s);
            printf("%d\n",a[id]);
        }
    }
    return 0;
}