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:\n",k); 38 for(int i = 1; i <= m; i++) { 39 ll d; 40 scanf("%lld", &d); 41 printf("%lld\n", query(d)); 42 } 43 } 44 return 0; 45 }
//還有, 如果root初始為1 tot一定也要初始為1 !!!!!!!!!!!(其實初始為0比較好, 玄學變快QAQ)