AcWing 143. 最大异或对 —— 神奇的二进制
题目描述
分析:
这里先回顾一下异或的操作。异或(Exclusive or, XOR)为当两两数值相同时为否,而数值不同时为真。在编程语言中,常写作 p ^ q
。直观如下:
在本题当中可以对给出的 NNN 个整数进行暴力枚举同时记录两两最大的异或结果。很不幸暴力的做法会超时,下面给出暴力代码:
int res = 0
for (int i = 0; i < n; i ++) // 枚举第一个数
{for (int j = 0; j < i; j ++) // 枚举第二个数,可以避免重复枚举res = max(res, a[i] ^ a[j})
}
那我们要进行优化,具体为对内层循环进行优化。由于数据小于 2312^{31}231,因此可以将每个整数看成长度为 313131 位的二进制串。那能使 a[i]a[i]a[i] 与其异或值最大的整数一定是高位至低位有尽可能多的不同位(使异或结果可以尽可能多地获得1)。流程如下所示,假设 a[i]a[i]a[i] 为313131位的二进制数101110...1101110...1101110...1。在贪心准则下每次往能获得最大值的方向走,若其他整数不能使当前位获得最大值(假设 a[i]a[i]a[i] 当前位为0,而tire树中只有0可以走),也只能先将就一下往这里走,等下一位再追求最好的。直至走完 a[i]a[i]a[i]。
注:对于 a[i]a[i]a[i] 来讲,它面临的 trie树,是由 a[0]...a[i−1]a[0] ... a[i-1]a[0]...a[i−1] 构建的。
以上就是利用trie树优化内层的循环的思想,并且每次 a[i]a[i]a[i] 只和 a[j](j<i)a[j](j < i)a[j](j<i) 的数进行运算即可,这是因为 p ^ q = q ^ p
(^ 为异或运算)。
另外需要注意一个细节,对于每一个 a[i](0≤i≤N)a[i](0≤i≤N)a[i](0≤i≤N)是先进行对其进行最大异或值查询再插入进 trie树还是先插入再查询呢?这里我们采用先插入再查询的流程,因为对于第一个整数来讲,trie树为空,若此时进行异或运算可能会非法的结果;若先插入再查询,则第一个数一定是和自己做异或运算,由于异或运算的性质,可以得出结果一定为000。
别扭的位运算
由于本题都是对二进制数进行操作,因此我打算先提前把位运算说清楚,这样在看代码时会事半功倍。
左移运算(<<):在C++中,若对整数进行左移操作,如 x << 1
,即把每一位向前(左)推一位后在末尾补上000,相当于将这个数放大222倍。这是为什么呢?请看下图:
右移运算(>>):在C++中,若对整数进行左移操作,如 x >> 1
,即把每一位向后(右)推一位,并把推出去的数去掉,相当于将这个数缩小222倍。具体细节可将左移推导中的乘法转换为除法即可。同理也要搞清楚左移 kkk 位以及右移 kkk 位的含义。
有了左右移的概念之后,我们来看一下代码中经常出现的位运算操作之一:x >> k & 1
。大家都将该操作称为“看看第 kkk 位(kkk 从000开始)”。该操作为将 xxx 的二进制表示右移 kkk 位后与0000...010000...010000...01按位求与运算。我想与运算大家肯定明白,那为什么是看看第 kkk 位呢?由于二进制只有000和111,求与运算后若为000,说明第 kkk 位是000;若是111,说明第 kkk 位是111。例见下图:
代码(C++)
#include <iostream>using namespace std;const int N = 100010, M = 31 * N;
int a[N], son[M][2], n, idx;void insert(int x)
{int p = 0;for (int i = 30; i >= 0; i --){// 取出 x 的第 i 位二进制数int u = x >> i & 1;if (!son[p][u]) son[p][u] = ++ idx;p = son[p][u];}
}int query(int x)
{int p = 0, res = 0;for (int i = 30; i >= 0; i --){int u = x >> i & 1;// 对于当前位的二进制数// 尽可能往其出现过的相反的方向走,假设当前位 u = 0// 若1的那个方向的 trie树枝干被创建则向那个方向走// 若没有被创建,则先将就一下走0的方向if (son[p][!u]){p = son[p][!u];res = (res << 1) + !u; // 将当前位加到左移后空出的第0位上}else {p = son[p][u];res = (res << 1) + u;}}return res;
}int main()
{cin >> n;for (int i = 0; i < n; i ++) cin >> a[i];int res = 0;for (int i = 0; i < n; i ++){// 先插入后运算是为了避免边界问题,对于第一个整数整个树为空// 若先将自己插入进去,则与自己的异或结果始终为0insert(a[i]);int t = query(a[i]);res = max(res, a[i] ^ t);}cout << res;
}
AcWing 143. 最大异或对 —— 神奇的二进制相关推荐
- AcWing 143. 最大异或对
题目连接 https://www.acwing.com/problem/content/145/ 思路 贪心的想,如果我们想找到一个异或的最大值,那么我们肯定想每一位最好都是相反的,如果没有这样的情况 ...
- 143. 最大异或对
模板:tire 复杂度:O(nlogn) 143. 最大异或对 #include <iostream> #include <algorithm> using namespace ...
- 143. 最大异或对【贪心 trie】
贪心,尽可能走不同的路. #include<bits/stdc++.h> using namespace std; const int N=1e5+10; typedef long lon ...
- 树状数组-神奇的二进制
树状数组是解决快速更新以及统计数组某段区间总和,设一个数组A[1-N],需要计算A[M-K]的总和,暴力解法需要O(K-M),如果我们求出sum(1-K)和sum(1-M),那么答案就是sum(1-M ...
- 神奇的二进制转换和运算
二进制的运算 正整数和二进制互转 二进制如何区分正负? 二进制位左边首位为0为正数,例如:6 --->00000110:1为负数,例如:-6---->11111010 正整数转二进制的过程 ...
- 数学小魔术——神奇的二进制
小魔术--猜数游戏 心中默想一个小于50的两位数 接着,我问你在以下的6张卡片中,哪几张卡片中有你想的那个数?(为什么是6张卡片,和50有什么关系) 最后,我不费吹灰之力就能猜出这个数. 这六张卡片有 ...
- AcWing基础算法课Level-2 第二讲 数据结构
AcWing基础算法课Level-2 第二讲 数据结构 单链表 AcWing 826. 单链表3453人打卡 双链表 AcWing 827. 双链表2865人打卡 栈 AcWing 828. 模拟栈3 ...
- Acwing算法基础课学习笔记
Acwing学习笔记 第一章 基础算法 快速排序 归并排序 二分查找 前缀和与差分 差分 位运算 离散化 第二章 数据结构 单链表 双链表 栈 队列 单调栈 单调队列 KMP算法 Trie 并查集 堆 ...
- 0x16.基本数据结构 — Trie树(字典树)+ A C 自 动 机
目录 用TrieTrieTrie树来处理整数异或问题是真的舒服! 一.TrieTrieTrie树 TrieTrieTrie的基本操作 0.初始化 1.插入 2.检索 二.TrieTrieTrie树例题 ...
- 0x10基本数据结构
0x11 栈 栈是一种后进先出的线性数据结构 AcWing 41.包含min函数的栈 维护两个栈,一个记录栈的值,另一个单调栈,记录下当前的最小值即可 coding AcWing 128. 编辑器 开 ...
最新文章
- 物联网在“最后一公里”投递中的应用
- Linux内核抢占实现机制分析【转】
- JavaScript有限状态机实现方式
- 树莓派:和电脑之间的串口编程,以及树莓派的备份
- 《走遍中国》珍藏版(八)
- Openstack的镜像上传原理
- Adidas、金拱门、KFC、乐天玛特,零售巨头的选址秘诀都在数据里了
- android 动态绘制布局,Android代码和绘制曲线中按钮和绘图板的动态布局
- 落户北京经开区 小米汽车首车预计2024年下线并量产 网友:开始存钱!
- 计算机科技英语论文,计算机科技英语论文.doc
- SSL Library Compare
- flash+xml 制作电子相册教程
- win7怎么把计算机放到桌面6,手机投屏到电脑win7最简单具体操作步骤
- 量子十问之四:“薛定谔猫”为什么会自然死亡?
- SpringSecurity登陆受权出现This object has not been built问题解决
- 工作中常见的两种谬误
- thinkphp5.1和5.0下的中文分词
- 前端性能优化之WebP图片
- WPF嵌入技术1_嵌入WPF到cad(MFC,win32窗体),Win32API嵌入WPF位置跳走的解决方案
- 【多媒体编解码】Openmax IL (一)官方文档概述