HDU 4825 Xor Sum (trie树处理异或)
Xor Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 3647 Accepted Submission(s): 1595
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。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
Output
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。
对于每个询问,输出一个正整数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
分析
要求求出原集合中与所给的数异或值最大的数。
建立一颗trie树,左边是0,右边是1。将所有数放到trie树中。
那么,对于给定的数x,将x二进制分解,在trie中从高位往低位走,每一位最好是和x不同(异或:不同为1,相同为0)。
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 const int N = 5000100; 7 8 inline char nc() { 9 static char buf[100000],*p1=buf,*p2=buf; 10 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 11 } 12 inline int read() { 13 int x = 0,f = 1;char ch = nc(); 14 for (; ch<'0'||ch>'9'; ch=nc()) if(x=='-')f=-1; 15 for (; ch>='0'&&ch<='9'; ch=nc()) x=x*10+ch-'0'; 16 return x * f; 17 } 18 struct Trie{ 19 int val[N],ch[N][2]; 20 int cnt; 21 void init() { 22 memset(ch,0,sizeof(ch)); 23 memset(val,0,sizeof(val)); 24 cnt = 0; 25 } 26 void Insert(int x) { 27 int u = 0; 28 for (int i=31; i>=0; --i) { 29 int c = (x&(1<<i)) > 0; 30 if (!ch[u][c]) ch[u][c] = ++cnt; 31 u = ch[u][c]; 32 } 33 val[u] = x; 34 } 35 int Query(int x) { 36 int u = 0; 37 for (int i=31; i>=0; --i) { 38 int c = (x&(1<<i))>0; 39 if (ch[u][!c]) u = ch[u][!c]; 40 else if(ch[u][c]) u = ch[u][c]; // 41 } 42 return val[u]; 43 } 44 }t; 45 46 int main () { 47 int T = read(); 48 for (int Case=1; Case<=T; ++Case) { 49 t.init(); 50 int n = read(),m = read(); 51 for (int i=1; i<=n; ++i) { 52 int a = read(); 53 t.Insert(a); 54 } 55 printf("Case #%d:\n",Case); 56 while (m--) { 57 int a = read(); 58 printf("%d\n",t.Query(a)); 59 } 60 } 61 return 0; 62 }