如何在保持最大值和最小值的同时更新段树中的范围?

时间:2012-08-05 06:21:02

标签: c++ algorithm data-structures segment-tree

我正在从数据数组中实现分段树,我还想在更新数据范围时保持树的最大/最小值。以下是我在本教程http://p--np.blogspot.com/2011/07/segment-tree.html之后的初步方法。 不幸的是它根本不起作用,逻辑对我来说很有意义,但我对be有点困惑,我想这是data数组的范围?或者它是树的实际范围?根据我的理解,max_segment_tree[1]应该保留范围max的{​​{1}},[1, MAX_RANGE]应该保持范围min_segment_tree[1]的{​​{1}}。

min

修改 添加测试用例:

[1,  MAX_RANGE]

2 个答案:

答案 0 :(得分:5)

您需要单独存储每个间隔的最大值/最小值,以及添加了哪些值(只是它们的总和)。以下是它可能出错的方式:

假设我们正在为数组[5,1,3,7]构建一个树(我只在这里显示最小树)。树看起来像这样:

   1
 1   3
5 1 3 7

然后我们在整个区间加1。树看起来像这样:

   2
 1   3
5 1 3 7

因为传播已在第一个节点上停止,因为更新的时间间隔完全覆盖了它。

然后在范围[0-1]中加1。此范围不包括第一个节点的整个间隔,因此我们更新子节点,然后将整个间隔的min(即第一个节点的值)设置为节点2和3的min。是结果树:

   2
 2   3
5 1 3 7

这是错误的地方 - 数组中没有元素2,但是树声称整个数组的最小值是2.这是因为树的较低级别实际上从未得到信息它们的值已经增加 - 第二个节点没有意识到它的值不是[5,1]而是[6,2]。

为了使其正常工作,您可以添加第三个数组,以保留已添加到整个时间间隔的值 - 例如int added_to_interval[3 * MAX_RANGE + 1];。然后,当您更新整个时间间隔(i <= b && j >= e)的情况时,您还必须使用added_to_interval[position]增加value。此外,当上升树以从子项的值更新节点时,您还必须添加已添加到整个时间间隔的节点(例如max_segment_tree[position] = max(max_segment_tree[position * 2], max_segment_tree[position * 2 + 1]) + added_to_interval[position];)。

修改

以下是对其进行更改的代码:

if (i <= b && j >= e) {
    max_segment_tree[position] += value;
    min_segment_tree[position] += value;
    added_to_interval[position] += value;
    return;
}

...

update_tree(position * 2 , b , (b + e) / 2 , i, j, value);
update_tree(position * 2 + 1 , (b + e) / 2 + 1 , e , i, j, value);

max_segment_tree[position] = max(max_segment_tree[position * 2], max_segment_tree[position * 2 + 1]) + added_to_interval[position];
min_segment_tree[position] = min(min_segment_tree[position * 2], min_segment_tree[position * 2 + 1]) + added_to_interval[position];

我没有对它进行过广泛的测试 - 我将它留给你,但我尝试了一些似乎正常工作的例子。

另外,我认为数组中不需要3 * MAX_RANGE + 1个元素 - 2 * MAX_RANGE或类似的元素就足够了。

答案 1 :(得分:3)

[b,e] 是范围,由 * _ segment_tree [position] 覆盖, [i,j] 是当前查询范围。
关于范围存储:
* _ segment_tree [1] 保存整个数据数组的 max / min - 它是树的根,因为基于数组的二叉树必须从索引1 即可。这是因为树的 n 第一节点的子节点编号为 2 * n 2 * n + 1 0 < / strong>不能用作 n ,因为在这种情况下 2 * n = n 。因此,如果 * _ segment_tree [k] 保持数据[b,e] 的最小值/最大值,则 * segment_tree [2 * k] 成立数据的最小值/最大值[b,(b + e)/ 2] * segment_tree [2 * k + 1] - 数据[(b +) e)/ 2 + 1,e] - 您可以在代码中看到这些标记。