码迷,mamicode.com
首页 > 其他好文 > 详细

9.最大异或对 Trie树

时间:2020-07-13 09:15:13      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:res   循环   cin   max   i++   font   最大   span   节点   

技术图片

 可以选俩一样的数,但自己异或自己结果是0,不是最优解

预备知识,啥是异或

技术图片

 技术图片

 暴力做法就是两层for循环枚举所有可能

 暴力的思路就是

1:首先选定一个Ai(1 <= i <= n)

2:在A1 ~ An中选择一个数Aj,使得Ai ^ Aj的值最大

突破点在第2步

首先Ai一定小于等于31位,也就是0 <= Ai <= 2 ^ 31 - 1

技术图片

 本题思路:

首先对所有的Ai,根据每一位的0和1,建立一个Trie树

技术图片

 然后对于每一个固定的Ai的话

在Trie树中寻找,从根节点往下走

每次尽量往和Ai这一位上的数字不同的数字这一个分支上走,这样才能使得两个数异或出来的值最大

模拟样例

技术图片

 时间复杂度10 ^ 5 * 31

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 100010, M = 4e6 + 10;
 4 //M是Trie的总节点个数 = 10 ^ 5 * 31
 5 int a[N], son[M][2], idx;
 6 void insert(int x) {
 7     int p = 0;
 8     for (int i = 30; i >= 0; i--) {
 9         int &s = son[p][x >> i & 1];
10         if (!s) {
11             s = ++ idx; //创建新结点
12         }
13         p = s;
14     }
15 }
16 int query(int x) { //找到和x异或值最大的结果
17     int p = 0;
18     int res = 0;
19     for (int i = 30; i >= 0; i--) {
20         int s = x >> i & 1;
21         if (son[p][!s]) {
22             res += 1 << i;
23             p = son[p][!s];
24         } else {
25             p = son[p][s];
26         }
27     }
28     return res;
29 }
30 int main() {
31     int n;
32     cin >> n;
33     for (int i = 0; i < n; i++) {
34         cin >> a[i];
35         insert(a[i]);
36     }
37     int res = 0;
38     for (int i = 0; i < n; i++) {
39         res = max(res, query(a[i]));
40     }
41     cout << res << endl;
42     return 0;
43 }

 

9.最大异或对 Trie树

标签:res   循环   cin   max   i++   font   最大   span   节点   

原文地址:https://www.cnblogs.com/fx1998/p/13290843.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!