字典树求异或值

先上模板

 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 */
时间: 2024-11-08 03:34:05

字典树求异或值的相关文章

POJ 3764 The xor-longest Path ( 字典树求异或最值 &amp;&amp; 异或自反性质 &amp;&amp; 好题好思想)

题意 : 给出一颗无向边构成是树,每一条边都有一个边权,叫你选出一条路,使得此路所有的边的异或值最大. 分析 : 暴力是不可能暴力的,这辈子不可能暴力,那么来冷静分析一下如何去做.假设现在答案的异或值的最大的路的起点和终点分别为 a.b,这个异或值为了方便我用 ⊕(a, b) 表示,那么接下来有一个巧妙的转化 ⊕(a, b) == ⊕(root, a) ^ ⊕(root, b) ,这个转化在 LCA(a, b) == root 的时候明显成立,因为重复的部分会异或两次,相当于没有异或,而LCA(

POJ 3764 (异或+字典树)

早就听过用字典树求异或最大值,然而没做过.发现一碰到异或的题就GG,而且因为以前做过的一道类似的题(事实上并不类似)限制了思路,蠢啊= =. 题意:一棵带权的树,求任意两点间路径异或的最大值. 题解:设xor(a,b)是求a,b间路径的异或值,那么xor(a,b)=xor(root,a)^xor(root,b).因为如果LCA(a,b)==root时结论显然成立,不然的话就会有重复走过的部分,但是异或有性质x^x=0,所以LCA(a,b)!=root结论依然成立. 这样题目就很简单了.对每一个x

HDU1671 字典树

Phone List Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 18421    Accepted Submission(s): 6207 Problem Description Given a list of phone numbers, determine if it is consistent in the sense tha

2014牡丹江区域赛H(字典树)ZOJ3826

Hierarchical Notation Time Limit: 2 Seconds      Memory Limit: 131072 KB In Marjar University, students in College of Computer Science will learn EON (Edward Object Notation), which is a hierarchical data format that uses human-readable text to trans

[01字典树]求序列完美度(求区间最大异或值)

https://nanti.jisuanke.com/t/15531 解题关键:01字典树模板,用字典树保存每个数的二进制表示,从而动态维护区间上的最大异或值,注意添加和删除都可以用于一个change函数表示. 复杂度:$O(n\log n + {n^2}\log n)$ 1 #include<bits/stdc++.h> 2 #define maxn 1005 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 typedef long lon

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536 题意:有一个数组a[], 包含n个数,从n个数中找到三个数使得 (a[i]+a[j])⊕a[k]最大,i,j,k不同; 求异或的结果最大所以我们可以用01字典树,先把所有的数加入字典树中,从n个数中选出两个数a[i]和a[j], 先把他们从字典树中删除,然后找到与a[i]+a[j]异或最大的数,和结果取最大值即可: 最后不要忘记再把a[i]和a[j]添加到字典树中即可: #include<st

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

01字典树的是只含有0和1两种字符的字典树,在使用它的时候,把若干数字转成二进制后插入其中 在查询树中的哪个数字和给定数字有最大异或值的时候,从根开始贪心查询就ok了 HDU4825是一道裸题:给出n个数和m次询问,每次询问给出一个数x,问在n个数中哪个数与x异或值最大 1 #include<cstdio> 2 #include<cstring> 3 const int maxn=1000005; 4 int n,m,rt; 5 int a[maxn],v[3500005],s[3

字典树与01字典树

之前在做一道关于字符串匹配的题时,用到了字典树,但那时是用指针实现的,这次又遇到需要使用字典树这一结构的题,向学姐要了她的板子,学习了用数组实现的方法,对于解题而言,更为简短快速. 因为题目要求最大异或和,因此用的是01字典树,在字典树的基础上稍作修改. 以下为字典树和01字典树的普遍实现: 字典树 #include<iostream> #include<algorithm> using namespace std; struct Trie { static const int N

白话算法与数据结构之【字典树】

1. 什么是trie树 1.Trie树 (特例结构树) Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.      Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子