1. 程式人生 > >HDU4825 Xor Sum(貪心+Trie樹)

HDU4825 Xor Sum(貪心+Trie樹)

int for span 兩個 color string 線段 ret cas

今天本來想寫一個可持久化Trie樹,發現這道題一直沒做就補上了。

其實思路很簡單,假如說兩個數,和同一個數異或,很顯然,由於進制,高位上的一個1可以大於低位上所有1,所以即使後面的情況再糟糕,也比取後面好的值高(其實就是1000比0111大)

所以可以建一個01線段樹,從高往低插入一個數,比較時取反即可^_^

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int n,m,t;
 6 struct pnt{
 7     int child[2
]; 8 int end; 9 void res() 10 { 11 memset(child,0,sizeof(child)); 12 end=0; 13 } 14 }; 15 struct Trie{ 16 pnt tr[3300000]; 17 int siz; 18 void dst() 19 { 20 siz=0; 21 tr[0].res(); 22 } 23 void insert(int x,int l) 24 { 25 int root=0
; 26 for(int i=31;i>=0;i--) 27 { 28 int tmp=(bool)((x&(1<<i))!=0); 29 if(!tr[root].child[tmp]) 30 { 31 tr[root].child[tmp]=++siz; 32 tr[siz].res(); 33 } 34 root=tr[root].child[tmp];
35 } 36 tr[root].end=l; 37 } 38 int find(int x) 39 { 40 int root=0; 41 for(int i=31;i>=0;i--) 42 { 43 int tmp=(bool)((x&(1<<i))!=0); 44 tmp=tmp^1; 45 if(tr[root].child[tmp]) 46 root=tr[root].child[tmp]; 47 else 48 root=tr[root].child[1^tmp]; 49 } 50 return tr[root].end; 51 } 52 }trie; 53 int a[1000000]; 54 int main() 55 { 56 scanf("%d",&t); 57 for(int ccc=1;ccc<=t;ccc++) 58 { 59 printf("Case #%d:\n",ccc); 60 scanf("%d%d",&n,&m); 61 trie.dst(); 62 for(int i=1;i<=n;i++) 63 { 64 scanf("%d",&a[i]); 65 trie.insert(a[i],i); 66 } 67 for(int i=1;i<=m;i++) 68 { 69 int ask; 70 scanf("%d",&ask); 71 printf("%d\n",a[trie.find(ask)]); 72 } 73 } 74 return 0; 75 }

HDU4825 Xor Sum(貪心+Trie樹)