[ABC281F] Xor Minimization

div class="part">

Problem Statement

You are given a sequence of non-negative integers A=(a1,,aN).

Let us perform the following operation on A just once.

  • Choose a non-negative integer x. Then, for every i=1,,N, replace the value of ai with the bitwise XOR of ai and x.

Let M be the maximum value in A after the operation. Find the minimum possible value of M.

What is bitwise XOR? The bitwise XOR of non-negative integers A and B, AB, is defined as follows.
  • When AB is written in binary, the k-th lowest bit (k0) is 1 if exactly one of the k-th lowest bits of A and B is 1, and 0 otherwise.
For instance, 35=6 (in binary: 011101=110).

Constraints

  • 1N1.5×105
  • 0ai<230
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format:

$N$
$a_1$ $\ldots$ $a_N$

Output

Print the answer.


Sample Input 1

3
12 18 11

Sample Output 1

16

If we do the operation with x=2, the sequence becomes (122,182,112)=(14,16,9), where the maximum value M is 16.
We cannot make M smaller than 16, so this value is the answer.


Sample Input 2

10
0 0 0 0 0 0 0 0 0 0

Sample Output 2

0

Sample Input 3

5
324097321 555675086 304655177 991244276 9980291

Sample Output 3

805306368

异或的题目,考虑01trie。不妨先把trie建出来。考虑dp。

定义 dpi 为如果使用 trie 中点 i 的子树中的点构成的序列走。也就是如果把点 i 作为根节点,拎出来一颗 trie 树时的 答案。明显到叶子节点时,dpi=0

假设现在到了点 x,点 x 位于 01trie 的第 i 位。

如果他只有一个儿子有值,那么一定有办法把这一位变成0。所以可以直接继承。如果有两个儿子有值,那么这个 2i 是逃不掉的了,所以两个儿子中选择较小的那个再加上 2i 就行了。

但是这个 dp 中好像有个问题:我们整个序列中所有的数异或上的都是一个数,但是他当中并没有保证这个。是否会出现一个子树中某一位是1,另一个子树中某一位是0的情况呢?其实是会的,但是不影响答案。首先如果只有一个儿子,那就直接继承是没错的。但是如果有两个儿子,此时有 2^i 顶着,这比上面这种情况的影响会大很多。所以真正选择的方案按照两个儿子中 dp 值最小的那个儿子所选择的方案,大的那个不会有影响。

#include<bits/stdc++.h>
using namespace std;
const int N=1.5e5+5;
int a[N],tr[N*30][2],tag[N*30],f[N*30],n,idx(1);
void insert(int x)
{
	int u=1;
	for(int i=30;i>=0;i--)
	{
		f[u]=1<<i;
		if(!tr[u][x>>i&1])
			tr[u][x>>i&1]=++idx;
		u=tr[u][x>>i&1];
//		printf("%d\n",u); 
	}
	tag[u]=1;
}
int dfs(int x)
{
//	printf("%d\n",x);
	if(tag[x])
		return 0;
	if(!x)
		return -2000000000;
	int p=dfs(tr[x][0]),q=dfs(tr[x][1]);
	if(p>q)
		swap(p,q);
	return max(p+f[x],q);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",a+i);
		insert(a[i]);
	}
//	printf("%d %d\n",tr[0][0],tr[0][1]);
	printf("%d",dfs(1)); 
	return 0;
}
posted @   灰鲭鲨  阅读(82)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示