【题解】洛谷P10471 最大异或对 The XOR Largest Pair

洛谷P10471 最大异或对 The XOR Largest Pair

题目传送门

题意描述:

给定 \(N\) 个整数 \(A_1.A_2, \cdots, A_N\) 中选出两个进行异或计算,得到的结果最大是多少?

题意分析

考虑异或运算的特殊性:对于每一组进行异或运算的两个数 \((A_i,A_j)\) 的二进制位 ,相同得 \(0\) ,不同得 \(1\)

显然,我们需要尽量让两个数的二进制每一位不同优先保证高位不同

转化一下题目:在 \(N\)\(01\) 串中寻找从高到低差异最多的一个串

因为有多个待匹配串,所以我们使用 \(Trie\) 字典树储存并查找

算法步骤

从根开始查找,令当前节点为 \(u\),查询到了第 \(i\)

  1. 如果当前节点有与 \(i\) 相反的子节点 \(v\),则向 \(v\) 转移
  2. 如果没有则被迫转移到与 \(i\) 相同的节点

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e6,maxc = 2;
struct TRIE {
	struct node {
		int val; // 这条链对应的十进制值,0表示没有这个数
		int to[maxc];
	};
	int nodecnt = 0;
	node tree[maxn + 5];
	int num[40],len = 0; // 存二进制
	inline void insert(int x) { // 插入
		int tx = x; // 存原值
		memset(num,0,sizeof(num)); len = 0; // 拆分x
		while (x != 0) {
			num[++ len] = x % 2;
			x /= 2;
		}
		len = 36; // 每一个都存36位,较大值也能与较小值比较,如 111111111 ^ 0 => 111111111 ^ 000000000
		int u = 0; // 字典树操作
		for (int i = len;i >= 1;i --) {
			int t = num[i];
			if (tree[u].to[t] == 0) tree[u].to[t] = ++ nodecnt;
			u = tree[u].to[t];
		}
		tree[u].val = tx;
	}
	inline int find(int x) {
		int tx = x; // 存原值
		memset(num,0,sizeof(num)); len = 0; // 拆分x
		while (x != 0) {
			num[++ len] = x % 2;
			x /= 2;
		}
		len = 36;
		int u = 0;
		for (int i = len;i >= 1;i --) { // 字典树操作
			int t = num[i];
			if (tree[u].to[t ^ 1] != 0) u = tree[u].to[t ^ 1];
			else u = tree[u].to[t];
		}
		return tree[u].val ^ tx; // 答案为两值异或
	}
};
TRIE trie; // 字典树
int n;
int main() {
	scanf("%d",&n);
	int ans = 0;
	for (int i = 1;i <= n;i ++) {
		int x; scanf("%d",&x);
		ans = max(ans,trie.find(x)); // 在前i-1个数中找
		trie.insert(x); // 插入第i个数
	}
	printf("%d",ans);
	return 0;
}
posted @ 2025-04-14 22:50  nightmare_lhh  阅读(55)  评论(0)    收藏  举报