给定一个以1为根的N元树,以及一个由分配给每个节点的权重组成的数组val []和一个由{X,D}形式的查询组成的矩阵Q [] [] ,每个查询的任务可以找到分配给节点的所有权重中的最小值,该权重距节点X的距离最大为D。
例子:
Input: Q[][] = {{1, 2}, {2, 1}}, val[] = {1, 2, 3, 3, 5}
Output:
1
3
Explanation:
Query 1: X = 1, D = 2
The nodes atmost at a distance 2 from the node 1 are {1, 3, 4, 5} and the weights assigned to these nodes are {1, 3, 3, 5} respectively.
Therefore, the minimum weight assigned is 1.
Query 2: X = 2, D = 1
The nodes atmost at a distance 1 from node 2 is {2, 3} and the weights assigned to these nodes are {2, 3} respectively.
Therefore, the minimum weight assigned is 2.
Input: Q[][] = {{1, 2}}, val[] = {1, 2, 4}
Output: 1
天真的方法:
解决每个查询的最简单方法是遍历树并找到距离节点X最多距离D的所有节点,并找到分配给这些节点的所有权重中的最小值。
时间复杂度: O(Q * N)
辅助空间: O(1)
高效方法:
要优化上述方法,请按照以下步骤操作:
- 实现树的Euler Tour,并为树的每个节点分配一个索引。
- 现在,在每个索引处,将与节点关联的深度和值存储在数组中。
- 在阵列上构建合并排序树,然后根据节点的深度对范围进行排序。
- 对于每个查询,已知X子树的所有节点都位于in [X]和out [X]数组之间,其中in和out是节点执行DFS的索引。
- 在此范围内,找到距离最大为D的最小加权节点。构建合并排序树,并根据深度的增加顺序合并两个范围,并在合并排序树的每个节点的值中找到最小的前缀。
下面是上述方法的实现:
C++
1
/ \
4 5
/
3
/
2
1
/ \
2 3
时间复杂度: O(N * log(N)+ Q * log(N))
辅助空间: O(N * log N)