1. 程式人生 > >HDU 4825 01字典樹

HDU 4825 01字典樹

題目連結

題意:給定一個集合和多個詢問,每個詢問為一個數,輸出集合中的一個數使得該數與詢問的異或和最大。

思路:
經典題。

對於集合中的每一個數從高位到低位插入一棵01字典樹,然後對於每一個詢問的數x,將x二進位制分解後從高位進行匹配,儘量匹配相反的數(0匹配1,1匹配0),使異或後高位儘量出現1。

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
inline int read(){
    int
x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int A = 1e5 + 10; int Trie[A*16][2],val[A*16],tot,n,m,x; void init(){ tot = 0; memset(val,0,sizeof(val)); memset
(Trie,0,sizeof(Trie)); } void insert(ll v){ int u = 0; for(int i=32 ;i>=0 ;i--){ int c = (v>>i)&1; if(!Trie[u][c]) Trie[u][c] = ++tot; u = Trie[u][c]; } val[u] = v; } int query(ll v){ int u = 0; for(int i=32 ;i>=0 ;i--){ int c = (v>>i)&1
; if(Trie[u][c^1]) u = Trie[u][c^1]; else u = Trie[u][c]; } return val[u]; } int main(){ int T,_=1;T = read(); while(T--){ init();printf("Case #%d:\n",_++); n = read();m = read(); for(int i=1 ;i<=n ;i++){x = read();insert(x);} for(int i=1 ;i<=m ;i++){ x = read(); printf("%d\n",query(x)); } } return 0; }