Javatpoint标志
Javatpoint标志

段树-给定范围的和

让我们考虑下面的问题来理解段树。

我们有一个数组arr[0…]n - 1)。我们应该能够做到

  • 求从索引l到r中0 <= l <= r <= n-1的元素的和
  • 将数组中指定元素的值更改为新值x.我们需要做arr[i] = x其中0 <= i <= n-1。

使用嵌套循环的Range sum:

运行一个从l到r的循环并计算所提供范围内元素的和是一个简单的解决方案。只需输入arr[i] = x即可更改值。第一个操作需要O(n)时间,而第二个操作只需要O(1)时间。

使用前缀和的范围总数:

另一种方法是创建一个新数组,并将从start到I的总数放在第I个索引处。更新过程现在需要O(n)时间,而给定范围的总数可以在O(1)时间内计算出来。如果有很多查询操作和很少的更新,这可以很好地工作。

使用段树的范围总数:

最有效的方法是利用段树;我们可以在O(log(N))时间内使用段树来完成这两个操作。

段树表示

  • 输入数组中的元素是叶节点。
  • 每个内部节点显示叶节点是如何以某种方式合并的。对于某些问题,可能会有不同的合并。总结一个节点下的叶节点就是这个问题的合并。
  • 段树被显示为树的数组表示。每个节点在索引I处的左子节点是index (2* I +1),右子节点是index (2* I +2),父节点是index (I - 1) / 2)。
段树-给定范围的和

从提供的数组构建一个段树

我们首先检查段arr[0,…]n - 1)。每次,我们将当前段分成两半(假设它还没有成为长度为1的段),在两半上运行相同的操作,然后将每个这样的段的结果存储在适当的节点中。

除了最后一层,创建的段树的每一层都将被完全填充。此外,由于我们总是在每一层将每个片段分成两个,因此该树将是一个完整的二叉树。总是有n-1个内部节点因为创建的树总是一个有n个叶子的完整二叉树。因此,总共会有2*n - 1个节点。

提供的数组的段树有多高?

段树的高度为log2N。分配给段树的内容量将是(2 * 2log2n-1),因为树必须使用数组表示,并且必须保留父索引和子索引之间的关系。

搜索一个范围的和

如何计算的总和使用段树一旦它已经建立。计算元素和的算法如下。

在上述实现中,我们需要解决三种情况。

  • 在遍历树时,如果当前节点的取值范围不在指定范围内,则不将该节点的值添加到答案中。
  • 如果提供的范围与节点的范围部分重叠,则根据重叠的范围向左或向右移动。
  • 如果给定的范围与答案完全重叠,则将该范围添加到答案中。

更新值:

更新可以递归地执行,就像树构建和查询操作一样。提供给我们的是一个过时的索引。让diff表示新值。从段树的根开始,我们向每个在其范围内具有指定索引的节点追加diff。如果节点在其范围内没有指定的索引,则不修改节点。

c++代码

上述战略的应用情况如下:

输出:

给定范围内的值之和= 15更新后的给定范围内的值之和= 22
  • 时间复杂度:O (N * log (N))
  • 辅助空间:O (N)






Youtube 视频加入我们的Youtube频道:现在加入

反馈


帮助别人,请分享

脸谱网 推特 pinterest

学习最新教程


准备


热门的技术


b .技术/马华






Baidu
map