Xor Sum(讲解异或)【字典树】

Xor Sum

题目链接(点击)

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 6182    Accepted Submission(s): 2683

Problem Description

Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?

Input

输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数

### 蓝桥杯异或森林问题解法 #### 题目背景 蓝桥杯竞赛中,“异或森林”是一类涉及图论和位运算的经典算法题。这类题目通常会给出一棵树或者多个连通分量组成的森林,要求通过某种操作(通常是基于异或运算)完成特定目标。 --- #### 问题分析 在“异或森林”问题中,核心在于如何利用 **XOR 运算** 的特性来解决问题。以下是几个常见的思路: 1. **XOR 运算性质** XOR 是一种按位逻辑运算符,具有以下重要性质[^2]: - $ a \oplus b = c $ 则 $ a \oplus c = b $ - $ a \oplus a = 0 $ - $ a \oplus 0 = a $ 2. **树的遍历与路径求解** 对于给定的一棵树,可以通过深度优先搜索(DFS)或广度优先搜索(BFS)记录每条边上的权重,并结合 XOR 特性计算任意两点之间的路径权值之和[^3]。 3. **并查集优化** 如果问题是关于森林而非单棵树,则可能需要借助并查集维护各个连通分量的状态。对于每个连通分量内的节点对 $(u, v)$,可以快速查询其路径上所有边权值的 XOR 结果。 --- #### 解决方案 下面是一个通用的解决方案框架,适用于大多数“异或森林”类型的题目: ```python class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, u): if self.parent[u] != u: self.parent[u] = self.find(self.parent[u]) return self.parent[u] def union(self, u, v, weight): root_u = self.find(u) root_v = self.find(v) if root_u != root_v: if self.rank[root_u] < self.rank[root_v]: self.parent[root_u] = root_v elif self.rank[root_u] > self.rank[root_v]: self.parent[root_v] = root_u else: self.parent[root_v] = root_u self.rank[root_u] += 1 def solve_xor_forest(edges, queries, node_count): uf = UnionFind(node_count) edge_weights = {} # 初始化并查集和边权字典 for u, v, w in edges: uf.union(u, v, w) key = tuple(sorted((u, v))) edge_weights[key] = w results = [] for query in queries: u, v = query path_weight = 0 # 使用 DFS 或 BFS 计算路径上的 XOR 权重 visited = set() stack = [(u, 0)] while stack: current_node, xor_sum = stack.pop() if current_node == v: path_weight = xor_sum break if current_node not in visited: visited.add(current_node) for neighbor, weight in get_neighbors(current_node): # 假设有一个函数获取邻居节点 next_key = tuple(sorted((current_node, neighbor))) if next_key in edge_weights and neighbor not in visited: stack.append((neighbor, xor_sum ^ edge_weights[next_key])) results.append(path_weight) return results ``` --- #### 关键点说明 1. **并查集的作用** 并查集用于高效管理森林中的连通分量关系。当两个节点属于同一个连通分量时,可以直接进入下一步计算;否则返回无法到达的结果。 2. **路径 XOR 和的计算** 在构建好连通分量的基础上,使用 DFS/BFS 方法沿着路径逐步累加 XOR 权值,最终得到所需结果[^1]。 3. **时间复杂度** 整体时间复杂度取决于具体实现方式。假设输入规模为 $n$ 个节点和 $m$ 条边,则预处理阶段的时间复杂度约为 $O(m\alpha(n))$ (其中 $\alpha$ 表示反阿克曼函数),而每次查询的复杂度接近线性级别。 --- #### 示例应用 假设有如下输入数据: - 边集合 `edges`:[[1, 2, 5], [2, 3, 7]] - 查询列表 `queries`:[(1, 3), (2, 3)] 运行上述代码后可得输出 `[2, 7]`,表示对应查询路径上的 XOR 权值总和分别为 2 和 7。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值