【发布时间】:2022-01-08 16:47:59
【问题描述】:
我们得到了一个无向树,其节点为 N (1 to N),其根节点为节点 1。每个节点都有一个分配的值,
由数组表示 - A[i] 其中i:[1:N]。
我们需要回答 Q 类型的查询:
-> V X : 值V 和节点 X 的任何祖先之间的公共前缀的最长长度,包括 X , 以 62 位长度的二进制表示。
两个数字之间的共同前缀定义为:
例子:
4: 0..................0100 (62-bit binary representation)
6: 0..................0110
Considering both as 62-bit in it's binary representation.
Longest length of the common prefix is: 60 (as 60 left most bits are same.)
现在我们得到 N(节点数)、边、节点值(A[i])和查询,我们需要在最佳时间回答每个查询。
约束:
N <= 10^5, number of nodes
A[i] <= 10^9, value of each node
Q <= 10^5 ,number of queries
Edge[i] = (i, j) <= N
方法:
- 创建树并跟踪每个节点的直接父节点。
- 对于每个查询:
[V, X],遍历每个节点n(在从 X 到根的路径中)并将每个节点的值与V进行异或运算,并找到最重要的设置位每个 XOR 操作,并从所有这些操作中选择最小的一个。 - 所以查询的结果:
[V, X]:62 -(1 + Step-2 结果)。
有没有其他有效的方法来解决这个问题?由于上述方法在最坏的情况下需要
O(n^2)时间。
【问题讨论】:
-
你有关于树的形状的任何信息吗?
-
X和X的祖先的值有什么关系吗?
-
@user3386109,X 和 X 的祖先的值之间没有关系,它只是一个无向树,有 N 个节点(每个节点可以有 1 到 10^9 之间的任何值)有1 作为根节点。
-
一种方法是从左侧 (MSB) 查找设置位。对于两个数字,如果它们属于 [2^(n-1), 2^n) 范围,那么它们将从 MSB 设置相同的位,因此至少公共前缀是直到该位,然后很少额外检查后续位。如果它们不属于同一范围,则返回较大数字的设置 MSB 位位置 - 1 作为公共前缀。如果你已经知道树(不是动态创建的),你可以预先计算这些东西,并在查询时快速返回结果。
-
维护 N 位的映射和范围 [2^(n-1), 2^n) 的数字列表,并在创建树时(从输入)添加值相应的映射键列表。
标签: java c++ algorithm math data-structures