ARC122D XOR Game(博弈论?字典树,贪心)
题面
黑板上有
2
N
2N
2N 个数,第
i
i
i 个数为
A
i
A_i
Ai。
O
I
D
\rm OID
OID(OneInDark) 和
H
I
D
HID
HID(HandInDevil) 玩一个游戏,总共进行
N
N
N 轮,每轮
- H
I
D
HID
HID 选一个黑板上的数擦掉,令其为
x
x
x 。
- O
I
D
\rm OID
OID 再选一个黑板上的数擦掉,令其为
y
y
y 。
- 在笔记本上记下
x
⊕
y
x\oplus y
x⊕y 的值。
N
N
N 轮游戏之后,黑板上的数字会被擦光,笔记本上会记录有
N
N
N 个数字。最终的分数即为笔记本上最大的数字。
H
I
D
HID
HID 想让分数尽量大,
O
I
D
\rm OID
OID 想让分数尽量小。在两个人都采取最优策略的情况下,问最终的分数为多少?
1
≤
N
≤
2
⋅
1
0
5
1\leq N\leq 2\cdot 10^5
1≤N≤2⋅105,
0
≤
A
i
<
2
30
0\leq A_i<2^{30}
0≤Ai<230 。
题解
当
H
I
D
HID
HID 演算出最优方案时,他惊恐地发现:不论如何,整个游戏都被
O
I
D
\rm OID
OID 玩弄于指尖。
对于任何配对方案,
O
I
D
\rm OID
OID 都可以做到。不管
H
I
D
HID
HID 选的是什么数,
O
I
D
\rm OID
OID 只需要选与其配对的数就行了。所以我们要求的其实是找一种配对方案,使得异或后最大的值最小。
最大值最小,二分?
没有必要,这道题是求异或的最大值最小,和贪心算法、字典树的契合度极高。
经典的做法,先把所有数都放在字典树上再说。然后从最大的位开始考虑,尽量使得高位异或值都为
0
\tt0
0 ,我们就赢了。
当你遍历到字典树上某个点时(假设此时子树中有偶数个数字),会有两种情况:
- 左子树和右子树的数字个数都是偶数,此时肯定可以在两棵子树中分别匹配完,不需要越过该节点匹配,这样是最优的。然后,由于后面的位数不确定,分别遍历左子树和右子树,取最大值。
- 左子树和右子树的数字个数都是奇数,此时不论怎么匹配,总得有一组数字是要越过该节点的,也就是说这一位上免不了有一个
1
\tt1
1 了。那么就在这两棵子树上进行第二类遍历:每次遍历两个点
{
x
,
y
}
\tt\{x,y\}
{x,y},如果能够使当前位为
0
\tt0
0 ,就分别遍历
{
x
.
s
o
n
[
0
]
,
y
.
s
o
n
[
0
]
}
\tt\{x.son[0],y.son[0]\}
{x.son[0],y.son[0]} 和
{
x
.
s
o
n
[
1
]
,
y
.
s
o
n
[
1
]
}
\tt\{x.son[1],y.son[1]\}
{x.son[1],y.son[1]} 取最小值,如果不行(其中不论如何都有一棵子树没有数字时),就只好把返回值加上这一位的
1
\tt1
1,再遍历
{
x
.
s
o
n
[
0
]
,
y
.
s
o
n
[
1
]
}
\tt\{x.son[0],y.son[1]\}
{x.son[0],y.son[1]} 和
{
x
.
s
o
n
[
1
]
,
y
.
s
o
n
[
0
]
}
\tt\{x.son[1],y.son[0]\}
{x.son[1],y.son[0]} 取最小值加上。
最后的返回值就是答案了。
复杂度
Θ
(
N
l
o
g
A
)
\tt \Theta(N~log~A)
Θ(N log A) 。
CODE
#include<set>
#include<queue>
#include<bitset>
#include<cmath>
#include<ctime>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 400005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
#define INF 0x3f3f3f3f
#define SI set<int>::iterator
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int a[MAXN];
int tre[MAXN*30][2],cnt = 1;
int siz[MAXN*30];
void add(int x) {
int p = 1; siz[p] ++;
for(int i = 29;i >= 0;i --) {
int d = (x & (1<<i)) ? 1:0;
if(!tre[p][d]) tre[p][d] = ++ cnt;
p = tre[p][d]; siz[p] ++;
}return ;
}
int solve(int i,int a,int b,bool fl) {
if(i < 0) return 0;
if(!fl && siz[a] == 0) return 0;
if(siz[a] == 0 || siz[b] == 0) return (1<<(i+1))-1;
if(a == b) {
if(siz[tre[a][0]] & 1) {
return solve(i-1,tre[a][0],tre[a][1],1)+(1<<i);
}
return max(solve(i-1,tre[a][0],tre[a][0],0),solve(i-1,tre[a][1],tre[a][1],0));
}
else {
if((siz[tre[a][0]] > 0 && siz[tre[b][0]] > 0) || (siz[tre[a][1]] && siz[tre[b][1]])) {
return min(solve(i-1,tre[a][0],tre[b][0],1),solve(i-1,tre[a][1],tre[b][1],1));
}
return min(solve(i-1,tre[a][1],tre[b][0],1),solve(i-1,tre[a][0],tre[b][1],1)) + (1<<i);
}
}
int main() {
n = read();
for(int i = 1;i <= 2*n;i ++) {
a[i] = read();
add(a[i]);
}
printf("%d\n",solve(29,1,1,0));
return 0;
}
ARC122D XOR Game(博弈论?字典树,贪心)的更多相关文章
- HDU5715 XOR 游戏 二分+字典树+dp
当时Astar复赛的时候只做出1题,赛后补题(很长时间后才补,懒真是要命),发现这是第二简单的 分析: 这个题,可以每次二分区间的最小异或和 进行check的时候用dp进行判断,dp[i][j]代表前 ...
- HDU 4825 Xor Sum(经典01字典树+贪心)
Xor Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Total ...
- ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)
题目链接:http://poj.org/problem?id=3764 题目大意是在树上求一条路径,使得xor和最大. 由于是在树上,所以两个结点之间应有唯一路径. 而xor(u, v) = xor( ...
- CH 1602 - The XOR Largest Pair - [字典树变形]
题目链接:传送门 描述在给定的 $N$ 个整数 $A_1, A_2,\cdots,A_N$ 中选出两个进行xor运算,得到的结果最大是多少? 输入格式第一行一个整数 $N$,第二行 $N$ 个整数 $ ...
- HDU-4825 Xor Sum,字典树好题!
Xor Sum 一遍A了之后大呼一声好(keng)题!debug了两小时~~~~百度之星资格赛,可以. 题意:给你一个n个元素的数组,m次查询,每次输入一个数k要求从数组中找到一个数与k异或值最大,输 ...
- NEUOJ711 异星工厂 字典树+贪心
题意:你可以收集两个不相交区间的权值,区间权值是区间异或,问这两个权值和最大是多少 分析:很多有关异或求最大的题都是利用01字典树进行贪心,做这个题的时候我都忘了...最后是看别人代码的时候才想起来这 ...
- HDU 5536 Chip Factory 字典树+贪心
给你n个数,a1....an,求(ai+aj)^ak最大的值,i不等于j不等于k 思路:先建字典树,暴力i,j每次删除他们,然后贪心找k,再恢复i,j,每次和答案取较大的,就是答案,有关异或的貌似很多 ...
- hdu4825 01字典树+贪心
从高位向低位构造字典树,因为高位得到的数更大. AC代码: #include<cstdio> using namespace std; typedef long long LL; cons ...
- HDU--5269 ZYB loves Xor I (字典树)
题目电波: HDU--5269 ZYB loves Xor I 首先我们先解决 ai xor aj 每个数转化为二进制 我们用字典树统计 每个节点 0 和 1 的出现的个数 #include< ...
- HDU 5715 XOR 游戏 二分+字典树
XOR 游戏 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5715 Description 众所周知,度度熊喜欢XOR运算(XOR百科). 今天,它 ...
随机推荐
- Pytorch实现波阻抗反演
Pytorch实现波阻抗反演 1 引言 地震波阻抗反演是在勘探与开发期间进行储层预测的一项关键技术.地震波阻抗反演可消除子波影响,仅留下反射系数,再通过反射系数计算出能表征地层物性变化的物理参数.常用 ...
- 记一次ms17-010复现过程
最近碰到业务需要使用msf,以前了解过,后面都忘记了.这次干脆写下来,省的每次去找别人写的. 首先是使用nmap探测端口 nmap -O -sV 192.168.153.130 --script=vu ...
- python爬虫之protobuf协议介绍
前言 在你学习爬虫的知识过程中是否遇到下面的类型.如果有兴趣学习一下或者了解相关知识的,且不嫌在下才疏学浅,可以参考一下.欢迎各位网友的指正. 首先叙述一下问题的会出现的式样. 你可能会在请求参数中看 ...
- NC16618 [NOIP2008]排座椅
NC16618 [NOIP2008]排座椅 题目 题目描述 上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下 ...
- 2022省选前联考 AVL树/平衡树
题目描述 pks 得到了一棵 \(N\) 个节点,权值为 \(1\sim N\) 的 \(AVL\) 树,他觉得这棵树太大了,于是他想要删掉一些节点使得最后剩下的树恰好有 \(K\) 个节点.如果 p ...
- 蒸腾量与蒸散量(ET)数据、潜在蒸散量、实际蒸散量数据、气温数据、降雨量数据
数据下载链接:数据下载链接 引言 多种卫星遥感数据反演地表蒸腾与蒸散率(ET)产品是地理遥感生态网推出的生态环境类数据产品之一,产品包括2000-2009年三个波段RGB数据,值域0-252之 ...
- npm相关知识整理
语义化版本 major: 重大变化,不兼容老版本 minor: 新增功能,兼容老版本 patch: 修复bug,兼容老版本 依赖版本号 * 匹配最新版本的依赖 ^ 匹配最近的大版本依赖,比如^1.2. ...
- docker安装Nessus
Nessus家庭版最大只支持扫描16个主机,但利用docker无限使用,当然虚拟机快照也可以. 关于网上其他的破解版,我是没有成功(显示成功了,其实是自慰版),所以才弄得这个镜像 提供两个镜像(不懂d ...
- npm相关资料
npm 源的配置 命令行模式 npm install XXX --registry https://registry.npmmirror.com/ 项目模式 在项目更目录新建.npmrc 文件,内容 ...
- 如何优化API?8个实用技巧!【eolink翻译】
使用 API 可以让公司利用现代连接的力量来帮助他们扩大全球影响力.传输数据和改进集成.由于 API 使企业能够简化流程并增强可用性,所以企业会使用一些优化策略,不断优化流程,比如接下来要说到的8个技 ...