让我们考虑以下问题以理解段树。
我们有一个数组arr [0。 。 。 n-1]。我们应该能够
1找到从索引l到r的元素总和,其中0 <= l <= r <= n-1
2将数组的指定元素的值更改为新值x。我们需要做arr [i] = x,其中0 <= i <= n-1。
一个简单的解决方案是运行从l到r的循环,并计算给定范围内的元素之和。要更新值,只需做arr [i] = x。第一次操作花费O(n)时间,第二次操作花费O(1)时间。
另一个解决方案是创建另一个数组,并将从开始到i的和存储在此数组的第i个索引处。现在可以以O(1)的时间计算给定范围的总和,但是更新操作现在需要O(n)的时间。如果查询操作的数量很大且更新很少,则此方法效果很好。
如果查询次数和更新次数相等怎么办?给定数组后,是否可以在O(log n)时间内执行这两个操作?我们可以使用细分树在O(Logn)时间内完成这两项操作。
段树的表示
1.叶节点是输入数组的元素。
2.每个内部节点代表叶节点的一些合并。对于不同的问题,合并可能会有所不同。对于此问题,合并是节点下的叶子之和。
树的数组表示形式用于表示段树。对于索引i处的每个节点,左子节点在索引2 * i + 1处,右子节点在索引2 * i + 2处,父节点在索引处2 * i + 2处。
。
上段树在内存中的外观如何?
像堆一样,段树也表示为数组。此处的区别在于,它不是完整的二叉树。它是一棵完整的二叉树(每个节点都有0或2个子节点),并且除最后一个级别外,所有级别都已填充。与堆不同,最后一级在节点之间可能有间隙。以下是上图的细分树数组中的值。
Below is memory representation of segment tree for input array {1, 3, 5, 7, 9, 11}
st[] = {36, 9, 27, 4, 5, 16, 11, 1, 3, DUMMY, DUMMY, 7, 9, DUMMY, DUMMY}
伪值永远不会访问,也没有用。由于简单的数组表示,这会浪费一些空间。我们可以使用一些聪明的实现来优化这种浪费,但是求和和更新的代码变得更加复杂。
从给定数组构造细分树
我们从一个段arr [0开始。 。 。 n-1]。每次我们将当前段分成两半(如果尚未将其变成长度为1的段),然后在这两个半段上调用相同的过程,对于每个这样的段,我们将和存储在相应的节点中。
除最后一个级别外,已构建的段树的所有级别都将被完全填充。而且,该树将是完整的二叉树,因为我们总是在每个级别将分段分为两半。由于构造的树始终是具有n个叶子的完整二叉树,因此将有n-1个内部节点。因此,节点总数将为2 * n –1。请注意,这不包括虚拟节点。
表示段树的数组的总大小是多少?
如果n是2的幂,则没有虚拟节点。因此,段树的大小为2n-1(n个叶节点和n-1)个内部节点。如果n不是2的幂,则树的大小将为2 * x – 1,其中x是大于n的2的最小幂。例如,当n = 10时,表示段树的数组的大小为2 * 16-1 = 31。
关于大小的另一种解释是基于heignt。段树的高度将为
。由于树是使用数组表示的,并且必须保持父索引和子索引之间的关系,因此分配给段树的内存大小将是
。
查询给定范围的总和
构造树后,如何使用构造的分段树获取总和。以下是获取元素总和的算法。
int getSum(node, l, r)
{
if the range of the node is within l and r
return value in the node
else if the range of the node is completely outside l and r
return 0
else
return getSum(node's left child, l, r) +
getSum(node's right child, l, r)
}
更新值
像树构建和查询操作一样,更新也可以递归完成。给我们一个需要更新的索引。令diff为要添加的值。我们从段树的根开始,将diff添加到在其范围内具有给定索引的所有节点。如果节点在其范围内没有给定的索引,则我们不会对该节点进行任何更改。
执行:
以下是段树的实现。该程序为任何给定的数组实现了段树的构造。它还实现了查询和更新操作。
C++
// C++ program to show segment tree operations like construction, query
// and update
#include
using namespace std;
// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) { return s + (e -s)/2; }
/* A recursive function to get the sum of values in the given range
of the array. The following are parameters for this function.
st --> Pointer to segment tree
si --> Index of current node in the segment tree. Initially
0 is passed as root is always at index 0
ss & se --> Starting and ending indexes of the segment represented
by current node, i.e., st[si]
qs & qe --> Starting and ending indexes of query range */
int getSumUtil(int *st, int ss, int se, int qs, int qe, int si)
{
// If segment of this node is a part of given range, then return
// the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment overlaps with the given range
int mid = getMid(ss, se);
return getSumUtil(st, ss, mid, qs, qe, 2*si+1) +
getSumUtil(st, mid+1, se, qs, qe, 2*si+2);
}
/* A recursive function to update the nodes which have the given
index in their range. The following are parameters
st, si, ss and se are same as getSumUtil()
i --> index of the element to be updated. This index is
in the input array.
diff --> Value to be added to all nodes which have i in range */
void updateValueUtil(int *st, int ss, int se, int i, int diff, int si)
{
// Base Case: If the input index lies outside the range of
// this segment
if (i < ss || i > se)
return;
// If the input index is in range of this node, then update
// the value of the node and its children
st[si] = st[si] + diff;
if (se != ss)
{
int mid = getMid(ss, se);
updateValueUtil(st, ss, mid, i, diff, 2*si + 1);
updateValueUtil(st, mid+1, se, i, diff, 2*si + 2);
}
}
// The function to update a value in input array and segment tree.
// It uses updateValueUtil() to update the value in segment tree
void updateValue(int arr[], int *st, int n, int i, int new_val)
{
// Check for erroneous input index
if (i < 0 || i > n-1)
{
cout<<"Invalid Input";
return;
}
// Get the difference between new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(st, 0, n-1, i, diff, 0);
}
// Return sum of elements in range from index qs (quey start)
// to qe (query end). It mainly uses getSumUtil()
int getSum(int *st, int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n-1 || qs > qe)
{
cout<<"Invalid Input";
return -1;
}
return getSumUtil(st, 0, n-1, qs, qe, 0);
}
// A recursive function that constructs Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se, int *st, int si)
{
// If there is one element in array, store it in current node of
// segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the sum of values in this node
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, st, si*2+1) +
constructSTUtil(arr, mid+1, se, st, si*2+2);
return st[si];
}
/* Function to construct segment tree from given array. This function
allocates memory for segment tree and calls constructSTUtil() to
fill the allocated memory */
int *constructST(int arr[], int n)
{
// Allocate memory for the segment tree
//Height of segment tree
int x = (int)(ceil(log2(n)));
//Maximum size of segment tree
int max_size = 2*(int)pow(2, x) - 1;
// Allocate memory
int *st = new int[max_size];
// Fill the allocated memory st
constructSTUtil(arr, 0, n-1, st, 0);
// Return the constructed segment tree
return st;
}
// Driver program to test above functions
int main()
{
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr)/sizeof(arr[0]);
// Build segment tree from given array
int *st = constructST(arr, n);
// Print sum of values in array from index 1 to 3
cout<<"Sum of values in given range = "<C
// C program to show segment tree operations like construction, query
// and update
#include
#include
// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) { return s + (e -s)/2; }
/* A recursive function to get the sum of values in given range
of the array. The following are parameters for this function.
st --> Pointer to segment tree
si --> Index of current node in the segment tree. Initially
0 is passed as root is always at index 0
ss & se --> Starting and ending indexes of the segment represented
by current node, i.e., st[si]
qs & qe --> Starting and ending indexes of query range */
int getSumUtil(int *st, int ss, int se, int qs, int qe, int si)
{
// If segment of this node is a part of given range, then return
// the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment overlaps with the given range
int mid = getMid(ss, se);
return getSumUtil(st, ss, mid, qs, qe, 2*si+1) +
getSumUtil(st, mid+1, se, qs, qe, 2*si+2);
}
/* A recursive function to update the nodes which have the given
index in their range. The following are parameters
st, si, ss and se are same as getSumUtil()
i --> index of the element to be updated. This index is
in the input array.
diff --> Value to be added to all nodes which have i in range */
void updateValueUtil(int *st, int ss, int se, int i, int diff, int si)
{
// Base Case: If the input index lies outside the range of
// this segment
if (i < ss || i > se)
return;
// If the input index is in range of this node, then update
// the value of the node and its children
st[si] = st[si] + diff;
if (se != ss)
{
int mid = getMid(ss, se);
updateValueUtil(st, ss, mid, i, diff, 2*si + 1);
updateValueUtil(st, mid+1, se, i, diff, 2*si + 2);
}
}
// The function to update a value in input array and segment tree.
// It uses updateValueUtil() to update the value in segment tree
void updateValue(int arr[], int *st, int n, int i, int new_val)
{
// Check for erroneous input index
if (i < 0 || i > n-1)
{
printf("Invalid Input");
return;
}
// Get the difference between new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(st, 0, n-1, i, diff, 0);
}
// Return sum of elements in range from index qs (quey start)
// to qe (query end). It mainly uses getSumUtil()
int getSum(int *st, int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n-1 || qs > qe)
{
printf("Invalid Input");
return -1;
}
return getSumUtil(st, 0, n-1, qs, qe, 0);
}
// A recursive function that constructs Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se, int *st, int si)
{
// If there is one element in array, store it in current node of
// segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the sum of values in this node
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, st, si*2+1) +
constructSTUtil(arr, mid+1, se, st, si*2+2);
return st[si];
}
/* Function to construct segment tree from given array. This function
allocates memory for segment tree and calls constructSTUtil() to
fill the allocated memory */
int *constructST(int arr[], int n)
{
// Allocate memory for the segment tree
//Height of segment tree
int x = (int)(ceil(log2(n)));
//Maximum size of segment tree
int max_size = 2*(int)pow(2, x) - 1;
// Allocate memory
int *st = new int[max_size];
// Fill the allocated memory st
constructSTUtil(arr, 0, n-1, st, 0);
// Return the constructed segment tree
return st;
}
// Driver program to test above functions
int main()
{
int arr[] = {1, 3, 5, 7, 9, 11};
int n = sizeof(arr)/sizeof(arr[0]);
// Build segment tree from given array
int *st = constructST(arr, n);
// Print sum of values in array from index 1 to 3
printf("Sum of values in given range = %dn",
getSum(st, n, 1, 3));
// Update: set arr[1] = 10 and update corresponding
// segment tree nodes
updateValue(arr, st, n, 1, 10);
// Find sum after the value is updated
printf("Updated sum of values in given range = %dn",
getSum(st, n, 1, 3));
return 0;
}
Java
// Java Program to show segment tree operations like construction,
// query and update
class SegmentTree
{
int st[]; // The array that stores segment tree nodes
/* Constructor to construct segment tree from given array. This
constructor allocates memory for segment tree and calls
constructSTUtil() to fill the allocated memory */
SegmentTree(int arr[], int n)
{
// Allocate memory for segment tree
//Height of segment tree
int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
//Maximum size of segment tree
int max_size = 2 * (int) Math.pow(2, x) - 1;
st = new int[max_size]; // Memory allocation
constructSTUtil(arr, 0, n - 1, 0);
}
// A utility function to get the middle index from corner indexes.
int getMid(int s, int e) {
return s + (e - s) / 2;
}
/* A recursive function to get the sum of values in given range
of the array. The following are parameters for this function.
st --> Pointer to segment tree
si --> Index of current node in the segment tree. Initially
0 is passed as root is always at index 0
ss & se --> Starting and ending indexes of the segment represented
by current node, i.e., st[si]
qs & qe --> Starting and ending indexes of query range */
int getSumUtil(int ss, int se, int qs, int qe, int si)
{
// If segment of this node is a part of given range, then return
// the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment overlaps with the given range
int mid = getMid(ss, se);
return getSumUtil(ss, mid, qs, qe, 2 * si + 1) +
getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);
}
/* A recursive function to update the nodes which have the given
index in their range. The following are parameters
st, si, ss and se are same as getSumUtil()
i --> index of the element to be updated. This index is in
input array.
diff --> Value to be added to all nodes which have i in range */
void updateValueUtil(int ss, int se, int i, int diff, int si)
{
// Base Case: If the input index lies outside the range of
// this segment
if (i < ss || i > se)
return;
// If the input index is in range of this node, then update the
// value of the node and its children
st[si] = st[si] + diff;
if (se != ss) {
int mid = getMid(ss, se);
updateValueUtil(ss, mid, i, diff, 2 * si + 1);
updateValueUtil(mid + 1, se, i, diff, 2 * si + 2);
}
}
// The function to update a value in input array and segment tree.
// It uses updateValueUtil() to update the value in segment tree
void updateValue(int arr[], int n, int i, int new_val)
{
// Check for erroneous input index
if (i < 0 || i > n - 1) {
System.out.println("Invalid Input");
return;
}
// Get the difference between new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(0, n - 1, i, diff, 0);
}
// Return sum of elements in range from index qs (quey start) to
// qe (query end). It mainly uses getSumUtil()
int getSum(int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n - 1 || qs > qe) {
System.out.println("Invalid Input");
return -1;
}
return getSumUtil(0, n - 1, qs, qe, 0);
}
// A recursive function that constructs Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se, int si)
{
// If there is one element in array, store it in current node of
// segment tree and return
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the sum of values in this node
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, si * 2 + 1) +
constructSTUtil(arr, mid + 1, se, si * 2 + 2);
return st[si];
}
// Driver program to test above functions
public static void main(String args[])
{
int arr[] = {1, 3, 5, 7, 9, 11};
int n = arr.length;
SegmentTree tree = new SegmentTree(arr, n);
// Build segment tree from given array
// Print sum of values in array from index 1 to 3
System.out.println("Sum of values in given range = " +
tree.getSum(n, 1, 3));
// Update: set arr[1] = 10 and update corresponding segment
// tree nodes
tree.updateValue(arr, n, 1, 10);
// Find sum after the value is updated
System.out.println("Updated sum of values in given range = " +
tree.getSum(n, 1, 3));
}
}
//This code is contributed by Ankur Narain Verma
Python3
# Python3 program to show segment tree operations like
# construction, query and update
from math import ceil, log2;
# A utility function to get the
# middle index from corner indexes.
def getMid(s, e) :
return s + (e -s) // 2;
""" A recursive function to get the sum of values
in the given range of the array. The following
are parameters for this function.
st --> Pointer to segment tree
si --> Index of current node in the segment tree.
Initially 0 is passed as root is always at index 0
ss & se --> Starting and ending indexes of the segment
represented by current node, i.e., st[si]
qs & qe --> Starting and ending indexes of query range """
def getSumUtil(st, ss, se, qs, qe, si) :
# If segment of this node is a part of given range,
# then return the sum of the segment
if (qs <= ss and qe >= se) :
return st[si];
# If segment of this node is
# outside the given range
if (se < qs or ss > qe) :
return 0;
# If a part of this segment overlaps
# with the given range
mid = getMid(ss, se);
return getSumUtil(st, ss, mid, qs, qe, 2 * si + 1) +
getSumUtil(st, mid + 1, se, qs, qe, 2 * si + 2);
""" A recursive function to update the nodes
which have the given index in their range.
The following are parameters st, si, ss and se
are same as getSumUtil()
i --> index of the element to be updated.
This index is in the input array.
diff --> Value to be added to all nodes
which have i in range """
def updateValueUtil(st, ss, se, i, diff, si) :
# Base Case: If the input index lies
# outside the range of this segment
if (i < ss or i > se) :
return;
# If the input index is in range of this node,
# then update the value of the node and its children
st[si] = st[si] + diff;
if (se != ss) :
mid = getMid(ss, se);
updateValueUtil(st, ss, mid, i,
diff, 2 * si + 1);
updateValueUtil(st, mid + 1, se, i,
diff, 2 * si + 2);
# The function to update a value in input array
# and segment tree. It uses updateValueUtil()
# to update the value in segment tree
def updateValue(arr, st, n, i, new_val) :
# Check for erroneous input index
if (i < 0 or i > n - 1) :
print("Invalid Input", end = "");
return;
# Get the difference between
# new value and old value
diff = new_val - arr[i];
# Update the value in array
arr[i] = new_val;
# Update the values of nodes in segment tree
updateValueUtil(st, 0, n - 1, i, diff, 0);
# Return sum of elements in range from
# index qs (quey start) to qe (query end).
# It mainly uses getSumUtil()
def getSum(st, n, qs, qe) :
# Check for erroneous input values
if (qs < 0 or qe > n - 1 or qs > qe) :
print("Invalid Input", end = "");
return -1;
return getSumUtil(st, 0, n - 1, qs, qe, 0);
# A recursive function that constructs
# Segment Tree for array[ss..se].
# si is index of current node in segment tree st
def constructSTUtil(arr, ss, se, st, si) :
# If there is one element in array,
# store it in current node of
# segment tree and return
if (ss == se) :
st[si] = arr[ss];
return arr[ss];
# If there are more than one elements,
# then recur for left and right subtrees
# and store the sum of values in this node
mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, st, si * 2 + 1) +
constructSTUtil(arr, mid + 1, se, st, si * 2 + 2);
return st[si];
""" Function to construct segment tree
from given array. This function allocates memory
for segment tree and calls constructSTUtil() to
fill the allocated memory """
def constructST(arr, n) :
# Allocate memory for the segment tree
# Height of segment tree
x = (int)(ceil(log2(n)));
# Maximum size of segment tree
max_size = 2 * (int)(2**x) - 1;
# Allocate memory
st = [0] * max_size;
# Fill the allocated memory st
constructSTUtil(arr, 0, n - 1, st, 0);
# Return the constructed segment tree
return st;
# Driver Code
if __name__ == "__main__" :
arr = [1, 3, 5, 7, 9, 11];
n = len(arr);
# Build segment tree from given array
st = constructST(arr, n);
# Print sum of values in array from index 1 to 3
print("Sum of values in given range = ",
getSum(st, n, 1, 3));
# Update: set arr[1] = 10 and update
# corresponding segment tree nodes
updateValue(arr, st, n, 1, 10);
# Find sum after the value is updated
print("Updated sum of values in given range = ",
getSum(st, n, 1, 3), end = "");
# This code is contributed by AnkitRai01
C#
// C# Program to show segment tree
// operations like construction,
// query and update
using System;
class SegmentTree
{
int []st; // The array that stores segment tree nodes
/* Constructor to construct segment
tree from given array. This constructor
allocates memory for segment tree and calls
constructSTUtil() to fill the allocated memory */
SegmentTree(int []arr, int n)
{
// Allocate memory for segment tree
//Height of segment tree
int x = (int) (Math.Ceiling(Math.Log(n) / Math.Log(2)));
//Maximum size of segment tree
int max_size = 2 * (int) Math.Pow(2, x) - 1;
st = new int[max_size]; // Memory allocation
constructSTUtil(arr, 0, n - 1, 0);
}
// A utility function to get the
// middle index from corner indexes.
int getMid(int s, int e)
{
return s + (e - s) / 2;
}
/* A recursive function to get
the sum of values in given range
of the array. The following
are parameters for this function.
st --> Pointer to segment tree
si --> Index of current node in the
segment tree. Initially
0 is passed as root is
always at index 0
ss & se --> Starting and ending indexes
of the segment represented
by current node, i.e., st[si]
qs & qe --> Starting and ending indexes of query range */
int getSumUtil(int ss, int se, int qs, int qe, int si)
{
// If segment of this node is a part
// of given range, then return
// the sum of the segment
if (qs <= ss && qe >= se)
return st[si];
// If segment of this node is
// outside the given range
if (se < qs || ss > qe)
return 0;
// If a part of this segment
// overlaps with the given range
int mid = getMid(ss, se);
return getSumUtil(ss, mid, qs, qe, 2 * si + 1) +
getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);
}
/* A recursive function to update
the nodes which have the given
index in their range. The following
are parameters st, si, ss and se
are same as getSumUtil() i --> index
of the element to be updated. This
index is in input array. diff --> Value
to be added to all nodes which have i in range */
void updateValueUtil(int ss, int se, int i,
int diff, int si)
{
// Base Case: If the input index
// lies outside the range of this segment
if (i < ss || i > se)
return;
// If the input index is in range of
// this node, then update the value
// of the node and its children
st[si] = st[si] + diff;
if (se != ss)
{
int mid = getMid(ss, se);
updateValueUtil(ss, mid, i, diff, 2 * si + 1);
updateValueUtil(mid + 1, se, i, diff, 2 * si + 2);
}
}
// The function to update a value
// in input array and segment tree.
// It uses updateValueUtil() to
// update the value in segment tree
void updateValue(int []arr, int n, int i, int new_val)
{
// Check for erroneous input index
if (i < 0 || i > n - 1)
{
Console.WriteLine("Invalid Input");
return;
}
// Get the difference between
// new value and old value
int diff = new_val - arr[i];
// Update the value in array
arr[i] = new_val;
// Update the values of nodes in segment tree
updateValueUtil(0, n - 1, i, diff, 0);
}
// Return sum of elements in range
// from index qs (quey start) to
// qe (query end). It mainly uses getSumUtil()
int getSum(int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n - 1 || qs > qe)
{
Console.WriteLine("Invalid Input");
return -1;
}
return getSumUtil(0, n - 1, qs, qe, 0);
}
// A recursive function that constructs
// Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int []arr, int ss, int se, int si)
{
// If there is one element in array,
// store it in current node of
// segment tree and return
if (ss == se) {
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements,
// then recur for left and right subtrees
// and store the sum of values in this node
int mid = getMid(ss, se);
st[si] = constructSTUtil(arr, ss, mid, si * 2 + 1) +
constructSTUtil(arr, mid + 1, se, si * 2 + 2);
return st[si];
}
// Driver code
public static void Main()
{
int []arr = {1, 3, 5, 7, 9, 11};
int n = arr.Length;
SegmentTree tree = new SegmentTree(arr, n);
// Build segment tree from given array
// Print sum of values in array from index 1 to 3
Console.WriteLine("Sum of values in given range = " +
tree.getSum(n, 1, 3));
// Update: set arr[1] = 10 and update
// corresponding segment tree nodes
tree.updateValue(arr, n, 1, 10);
// Find sum after the value is updated
Console.WriteLine("Updated sum of values in given range = " +
tree.getSum(n, 1, 3));
}
}
/* This code contributed by PrinciRaj1992 */
输出:
Sum of values in given range = 15
Updated sum of values in given range = 22
时间复杂度:
树构建的时间复杂度为O(n)。总共有2n-1个节点,并且在树结构中每个节点的值仅计算一次。
查询的时间复杂度为O(Logn)。要查询总和,我们在每个级别最多处理四个节点,并且级别数为O(Logn)。
更新的时间复杂度也是O(Logn)。要更新叶值,我们在每个级别处理一个节点,级别数为O(Logn)。
细分树|设置2(范围最小查询)
参考:
IIT Kanpur纸。