hdu 4825 01字典树

题意 给出n个数和m次询问,每次询问给出一个数x,问在n个数中哪个数与x异或值最大

思路:将给出的n个数放进0 1字典树,然后在询问的时候,倘若目前位为0,则去找相反的节点

 1 #include <queue>
 2 #include <vector>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <string.h>
 6 #include <iostream>
 7 #include <algorithm>
 8 using namespace std;
 9 int rt,a[1000005],v[3500005],s[3500005][2];
10 void in(int x,int id){
11     int i,u,op;
12     u=0;
13     for(i=31;i>=0;i--){
14         op=((x&(1<<i))!=0);
15         if(s[u][op]==0)
16         s[u][op]=rt++;
17         u=s[u][op];
18     }
19     v[u]=id;
20 }
21 int get(int x){
22     int i,u,op;
23     u=0;
24     for(i=31;i>=0;i--){
25         op=((x&(1<<i))!=0);
26         if(s[u][op^1]!=0)                       //尽可能走与当前位不同的点
27         u=s[u][op^1];
28         else
29         u=s[u][op];
30     }
31     return a[v[u]];
32 }
33 int main(){                                     //将每个数拆分成二进制从高位到低位插入到trie树中,
34     int t,n,m,i,j,u,cas;                        //每次询问都尽可能保证走不同与当前位不同的点,就
35     scanf("%d",&t);                             //保证了异或值最大
36     for(cas=1;cas<=t;cas++){
37         scanf("%d%d",&n,&m);
38         rt=1;
39         memset(s,0,sizeof(s));
40         memset(v,0,sizeof(v));
41         for(i=1;i<=n;i++){
42             scanf("%d",&a[i]);
43             in(a[i],i);
44         }
45         printf("Case #%d:\n",cas);
46         for(i=1;i<=m;i++){
47             scanf("%d",&u);
48             printf("%d\n",get(u));
49         }
50     }
51     return 0;
52 }

 

posted @ 2020-03-03 18:30  古比  阅读(199)  评论(0编辑  收藏  举报