段树-给定范围的和让我们考虑下面的问题来理解段树。 我们有一个数组arr[0…]n - 1)。我们应该能够做到
使用嵌套循环的Range sum:运行一个从l到r的循环并计算所提供范围内元素的和是一个简单的解决方案。只需输入arr[i] = x即可更改值。第一个操作需要O(n)时间,而第二个操作只需要O(1)时间。 使用前缀和的范围总数:另一种方法是创建一个新数组,并将从start到I的总数放在第I个索引处。更新过程现在需要O(n)时间,而给定范围的总数可以在O(1)时间内计算出来。如果有很多查询操作和很少的更新,这可以很好地工作。 使用段树的范围总数:最有效的方法是利用段树;我们可以在O(log(N))时间内使用段树来完成这两个操作。 段树表示
![]() 从提供的数组构建一个段树我们首先检查段arr[0,…]n - 1)。每次,我们将当前段分成两半(假设它还没有成为长度为1的段),在两半上运行相同的操作,然后将每个这样的段的结果存储在适当的节点中。 除了最后一层,创建的段树的每一层都将被完全填充。此外,由于我们总是在每一层将每个片段分成两个,因此该树将是一个完整的二叉树。总是有n-1个内部节点因为创建的树总是一个有n个叶子的完整二叉树。因此,总共会有2*n - 1个节点。 提供的数组的段树有多高?段树的高度为log2N。分配给段树的内容量将是(2 * 2log2n-1),因为树必须使用数组表示,并且必须保留父索引和子索引之间的关系。 搜索一个范围的和如何计算的总和使用段树一旦它已经建立。计算元素和的算法如下。 在上述实现中,我们需要解决三种情况。
更新值:更新可以递归地执行,就像树构建和查询操作一样。提供给我们的是一个过时的索引。让diff表示新值。从段树的根开始,我们向每个在其范围内具有指定索引的节点追加diff。如果节点在其范围内没有指定的索引,则不修改节点。 c++代码上述战略的应用情况如下:
下一个话题
2-3树(查找、插入、删除)
|