字典树求异或值

Posted 可是我不配

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字典树求异或值相关的知识,希望对你有一定的参考价值。

先上模板

 

 1 typedef long long ll;
 2 
 3 const int maxn=1e5+10;
 4 
 5 struct t
 6 {
 7     ll tree[32*maxn][3];//字典树的树部分
 8     ll val[32*maxn];//字典树的终止节点
 9     ll cnt;//字典树的大小
10     void init() //初始化字典树
11     {
12         cl(tree,0);
13         cl(val,0);
14         cnt=1;
15     }
16     void add(ll a)
17     {
18         int x=0,now;
19         for(int i=32; i>=0; i--)
20         {
21             now=((a>>i)&1); //当前位数
22             if(tree[x][now]==0) //没有的这个节点的话 加入这个节点
23             {
24                 cl(tree[cnt],0);
25                 val[cnt]=0;
26                 tree[x][now]=cnt++;
27             }
28             x=tree[x][now];
29         }
30         val[x]=a; //结尾标记
31     }
32     ll Search(ll a) //查找字典树中和a异或起来最大的值
33     {
34         int x=0,now;
35         for(int i=32; i>=0; i--)
36         {
37             now=!((a>>i)&1);
38             if(tree[x][now]) //如果和当前位相反的这个节点存在
39             {
40                 x=tree[x][now]; //那么继续找这个节点下的子树
41             }
42             else
43             {
44                 x=tree[x][!now]; //不存在就找自己这个节点下的子树
45             }
46         }
47         return val[x]; //结尾标记就是这个数字
48     }
49 } Trie;

 

接下来是例题

 

NBUT 1597 Find MaxXorSum 

 

题意:

给你n个数 让你找两个数使异或值最大

 

思路:

构造一棵字典树

用字典树求异或值

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #define cl(a,b) memset(a,b,sizeof(a))
 4 #define debug(a) cerr<<#a<<"=="<<a<<endl
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int maxn=1e5+10;
 9 
10 ll a[maxn];
11 
12 template<typename T>inline T max(T a,T b)
13 {
14     if(a>b) return a;
15     return b;
16 }
17 
18 struct t
19 {
20     ll tree[maxn*13][3],cnt;
21     void init()
22     {
23         cl(tree,0);
24         cnt=0;
25     }
26     void add(ll a)
27     {
28         int x=0,now;
29         for(int i=31; i>=0; i--)
30         {
31             now=((a>>i)&1);
32             if(tree[x][now]==0)
33             {
34                 tree[x][now]=++cnt;
35             }
36             x=tree[x][now];
37         }
38     }
39     ll Search(ll a)
40     {
41         int x=0,now;
42         ll ans=0;
43         for(int i=31; i>=0; i--)
44         {
45             ans<<=1;
46             now=!((a>>i)&1);
47             if(tree[x][now])
48             {
49                 x=tree[x][now];
50                 ans++;
51             }
52             else
53             {
54                 x=tree[x][!now];
55             }
56         }
57         return ans;
58     }
59 } Trie;
60 
61 int main()
62 {
63     int T;
64     scanf("%d",&T);
65     while(T--)
66     {
67         int n;
68         scanf("%d",&n);
69         Trie.init();
70         for(int i=0; i<n; i++)
71         {
72             scanf("%lld",&a[i]);
73             Trie.add(a[i]);
74         }
75         ll ans=0;
76         for(int i=0; i<n; i++)
77         {
78             ans=max(ans,Trie.Search(a[i]));
79         }
80         printf("%lld\n",ans);
81     }
82     return 0;
83 }/*
84 
85 2
86 4
87 1 2 3 4
88 3
89 7 12 5
90 
91 */

 

hdu 4825 Xor Sum

中文题意不解释

 

 1 #include<bits/stdc++.h>
 2 #define cl(a,b) memset(a,b,sizeof(a))
 3 #define debug(a) cerr<<#a<<"=="<<a<<endl
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 const int maxn=1e5+10;
 8 
 9 struct t
10 {
11     ll tree[32*maxn][3];
12     ll val[32*maxn],cnt;
13     void init()
14     {
15         cl(tree,0);
16         cl(val,0);
17         cnt=1;
18     }
19     void add(ll a)
20     {
21         int x=0,now;
22         for(int i=32; i>=0; i--)
23         {
24             now=((a>>i)&1);
25             if(tree[x][now]==0)
26             {
27                 cl(tree[cnt],0);
28                 val[cnt]=0;
29                 tree[x][now]=cnt++;
30             }
31             x=tree[x][now];
32         }
33         val[x]=a;
34     }
35     ll Search(ll a)
36     {
37         int x=0,now;
38         for(int i=32; i>=0; i--)
39         {
40             now=!((a>>i)&1);
41             if(tree[x][now])
42             {
43                 x=tree[x][now];
44             }
45             else
46             {
47                 x=tree[x][!now];
48             }
49         }
50         return val[x];
51     }
52 } Trie;
53 
54 int main()
55 {
56     int T,cas=1;
57     scanf("%d",&T);
58     while(T--)
59     {
60         int n,m,x;
61         scanf("%d%d",&n,&m);
62         Trie.init();
63         for(int i=0; i<n; i++)
64         {
65             scanf("%d",&x);
66             Trie.add(x);
67         }
68         printf("Case #%d:\n",cas++);
69         for(int i=0; i<m; i++)
70         {
71             scanf("%d",&x);
72             printf("%lld\n",Trie.Search(x));
73         }
74     }
75     return 0;
76 }/*
77 
78 2
79 3 2
80 3 4 5
81 1
82 5
83 4 1
84 4 6 5 6
85 3
86 
87 */

 

以上是关于字典树求异或值的主要内容,如果未能解决你的问题,请参考以下文章

Chip Factory---hdu5536(异或值最大,01字典树)

POJ 3764 (异或+字典树)

利用01字典树查询最大异或值

与数组中元素的最大异或值(字典树)(小于等于某元素的最大异或值)

数组中两个数的最大异或值(字典树||前缀树)

LeetCode每日一题——1707. 与数组中元素的最大异或值(字典树)