HDU 4825 Xor Sum
tql!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我以为trie树真的只是单纯的处理字符串问题
orz是我天真了(呸!就是做题少!!
很多异或和问题都可以用trie树解决
思路:
- 以0/1代替传统trie树中的字母, 先以读入的数字(分解二进制)建立trie树
- 异或:相同为0不同为1
- 将询问的数字分解二进制,优先选择与该位不同的,使异或值尽可能大(从高位开始), 如果没有, 则走与该位相同的
- WA了很久居然是因为v数组没有*32 QAQAQAQ //真。数组开小见祖宗
- 这个题我觉得还是很妙的qwq Mark一下qwq
代码qwq
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define ll long long 5 using namespace std; 6 const int sz = 100010; 7 int n, m, t, tot = 0; 8 int trie[sz*32][2], v[sz*32]; 9 void insert(ll x) { 10 int root = 0; 11 for(int i = 32; i >= 0; i--) { 12 int id = (x>>i)&1; 13 if(!trie[root][id]) trie[root][id] = ++tot; 14 root = trie[root][id]; 15 } 16 v[root] = x; 17 } 18 ll query(ll x) { 19 int root = 0; 20 for(int i = 32; i >= 0; i--) { 21 int id = (x>>i)&1; 22 if(trie[root][id^1]) root = trie[root][id^1]; 23 else root = trie[root][id]; 24 } 25 return v[root]; 26 } 27 int main() { 28 scanf("%d", &t); 29 for(int k = 1; k <= t; k++) { 30 memset(trie, 0, sizeof(trie)); 31 scanf("%d%d", &n, &m); 32 for(int i = 1; i <= n; i++) { 33 int d; 34 scanf("%d", &d); 35 insert(d); 36 } 37 printf("Case #%d: ",k); 38 for(int i = 1; i <= m; i++) { 39 ll d; 40 scanf("%lld", &d); 41 printf("%lld ", query(d)); 42 } 43 } 44 return 0; 45 }
//还有, 如果root初始为1 tot一定也要初始为1 !!!!!!!!!!!(其实初始为0比较好, 玄学变快QAQ)