HDU4825Xor Sum字典樹+異或 建樹
阿新 • • 發佈:2019-01-14
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 輸入包含若干組測試資料,每組測試資料包含若干行。
Output 對於每組資料,首先需要輸出單獨一行”Case #?:”,其中問號處應填入當前的資料組數,組數從1開始計算。
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; }