Xor Sum
http://acm.hdu.edu.cn/showproblem.php?pid=4825
分析:
01trie。
对每个数按长度从高位到低位建一条链,每个边上表示0/1,每次优先走不同的。每个数深度都是32,所以查询的时候走32步就行,并且每个点有边能够到达的点一定至少一个出边。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #define fi(s) freopen(s,"r",stdin); 12 #define fo(s) freopen(s,"w",stdout); 13 using namespace std; 14 typedef long long LL; 15 16 inline LL read() { 17 LL x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 18 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; 19 } 20 21 int ch[3200005][2]; 22 LL val[3200005]; 23 int Index = 1, nowCase; 24 25 void Insert(LL x) { 26 int u = 1; 27 for (int i=32; i>=0; --i) { 28 int c = (x >> i) & 1; // int c = x & (1 << i) !!! 29 if (!ch[u][c]) ch[u][c] = ++Index; 30 u = ch[u][c]; 31 } 32 val[u] = x; 33 } 34 LL query(LL x) { 35 int u = 1; 36 for (int i=32; i>=0; --i) { // 32步,到叶子节点 37 int c = (x >> i) & 1; 38 if (ch[u][!c]) u = ch[u][!c]; // 优先走不同的 39 else u = ch[u][c]; // 顺着存在的边走 40 } 41 return val[u]; 42 } 43 void solve() { 44 printf("Case #%d: ",++nowCase); 45 int n = read(), m = read(); 46 for (int i=1; i<=n; ++i) { 47 LL x = read(); Insert(x); 48 } 49 for (int i=1; i<=m; ++i) { 50 LL x = read(); 51 printf("%lld ", query(x)); 52 } 53 memset(ch, 0, sizeof(ch)); 54 memset(val, 0, sizeof(val)); 55 Index = 1; 56 } 57 int main() { 58 int T = read(); 59 while (T--) solve(); 60 return 0; 61 }