我们已经讨论了递归段树的实现。在这篇文章中,讨论了迭代实现。
让我们考虑以下问题,了解细分树。
我们有一个数组arr [0。 。 。 n-1]。我们应该能够
1找到从索引l到r的最小元素,其中0 <= l <= r <= n-1
2将数组的指定元素的值更改为新值x。我们需要做arr [i] = x,其中0 <= i <= n-1。
例子:
Input : 2, 6, 7, 5, 18, 86, 54, 2
minimum(2, 7)
update(3, 4)
minimum(2, 6)
Output : Minimum in range 2 to 7 is 2.
Minimum in range 2 to 6 is 4.
段树的迭代版本主要使用以下事实:对于索引i,树中的左子节点= 2 * i,右子节点= 2 * i + 1。可以通过parent = i / 2找到分段树数组中索引i的父级。因此,我们可以轻松地在树的各个层次上上下移动。首先,我们计算范围内的最小值,同时构造从叶节点开始并逐层爬升的树。在处理查询以查找范围内的最小值时,我们使用相同的概念。由于在最坏的情况下有(log n)个级别,因此查询花费log n时间。为了将特定索引更新为给定值,我们开始从叶节点开始更新段树,并通过在每次迭代中逐步上移级别来更新受当前节点更新影响的所有那些节点。更新也需要花费n倍的时间,因为我们必须从叶节点开始更新所有级别,在该叶节点处,我们将根据用户指定的确切索引来更新确切值。
C++
// CPP Program to implement iterative segment
// tree.
#include
#define ll long long
using namespace std;
void construct_segment_tree(vector& segtree,
vector &a, int n)
{
// assign values to leaves of the segment tree
for (int i = 0; i < n; i++)
segtree[n + i] = a[i];
/* assign values to internal nodes
to compute minimum in a given range */
for (int i = n - 1; i >= 1; i--)
segtree[i] = min(segtree[2 * i],
segtree[2 * i + 1]);
}
void update(vector& segtree, int pos, int value,
int n)
{
// change the index to leaf node first
pos += n;
// update the value at the leaf node
// at the exact index
segtree[pos] = value;
while (pos > 1) {
// move up one level at a time in the tree
pos >>= 1;
// update the values in the nodes in
// the next higher level
segtree[pos] = min(segtree[2 * pos],
segtree[2 * pos + 1]);
}
}
int range_query(vector& segtree, int left, int
right, int n)
{
/* Basically the left and right indices will move
towards right and left respectively and with
every each next higher level and compute the
minimum at each height. */
// change the index to leaf node first
left += n;
right += n;
// initialize minimum to a very high value
int mi = (int)1e9;
while (left < right) {
// if left index in odd
if (left & 1) {
mi = min(mi, segtree[left]);
// make left index even
left++;
}
// if right index in odd
if (right & 1) {
// make right index even
right--;
mi = min(mi, segtree[right]);
}
// move to the next higher level
left /= 2;
right /= 2;
}
return mi;
}
// Driver code
int main()
{
vector a = { 2, 6, 10, 4, 7, 28, 9, 11, 6, 33 };
int n = a.size();
/* Construct the segment tree by assigning
the values to the internal nodes*/
vector segtree(2 * n);
construct_segment_tree(segtree, a, n);
// compute minimum in the range left to right
int left = 0, right = 5;
cout << "Minimum in range " << left << " to "
<< right << " is "<< range_query(segtree, left,
right + 1, n) << "\n";
// update the value of index 3 to 1
int index = 3, value = 1;
// a[3] = 1;
// Contents of array : {2, 6, 10, 1, 7, 28, 9, 11, 6, 33}
update(segtree, index, value, n); // point update
// compute minimum in the range left to right
left = 2, right = 6;
cout << "Minimum in range " << left << " to "
<< right << " is " << range_query(segtree,
left, right + 1, n) << "\n";
return 0;
}
Java
// Java Program to implement iterative segment
// tree.
import java.io.*;
import java.util.*;
class GFG
{
static void construct_segment_tree(int[] segtree,
int[] a, int n)
{
// assign values to leaves of the segment tree
for (int i = 0; i < n; i++)
segtree[n + i] = a[i];
/*
* assign values to internal nodes
* to compute minimum in a given range
*/
for (int i = n - 1; i >= 1; i--)
segtree[i] = Math.min(segtree[2 * i], segtree[2 * i + 1]);
}
static void update(int[] segtree, int pos, int value, int n)
{
// change the index to leaf node first
pos += n;
// update the value at the leaf node
// at the exact index
segtree[pos] = value;
while (pos > 1)
{
// move up one level at a time in the tree
pos >>= 1;
// update the values in the nodes in
// the next higher level
segtree[pos] = Math.min(segtree[2 * pos],
segtree[2 * pos + 1]);
}
}
static int range_query(int[] segtree, int left,
int right, int n)
{
/*
* Basically the left and right indices will move
* towards right and left respectively and with
* every each next higher level and compute the
* minimum at each height. */
// change the index to leaf node first
left += n;
right += n;
// initialize minimum to a very high value
int mi = (int) 1e9;
while (left < right)
{
// if left index in odd
if ((left & 1) == 1)
{
mi = Math.min(mi, segtree[left]);
// make left index even
left++;
}
// if right index in odd
if ((right & 1) == 1)
{
// make right index even
right--;
mi = Math.min(mi, segtree[right]);
}
// move to the next higher level
left /= 2;
right /= 2;
}
return mi;
}
// Driver Code
public static void main(String[] args)
{
int[] a = {2, 6, 10, 4, 7, 28, 9, 11, 6, 33};
int n = a.length;
/*
* Construct the segment tree by assigning
* the values to the internal nodes
*/
int[] segtree = new int[2 * n];
construct_segment_tree(segtree, a, n);
// compute minimum in the range left to right
int left = 0, right = 5;
System.out.printf("Minimum in range %d to %d is %d\n",
left, right, range_query(segtree,
left, right + 1, n));
// update the value of index 3 to 1
int index = 3, value = 1;
// a[3] = 1;
// Contents of array : {2, 6, 10, 1, 7, 28, 9, 11, 6, 33}
update(segtree, index, value, n); // point update
// compute minimum in the range left to right
left = 2;
right = 6;
System.out.printf("Minimum in range %d to %d is %d\n",
left, right, range_query(segtree,
left, right + 1, n));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python3 program to implement
# iterative segment tree.
def construct_segment_tree(segtree, a, n):
# assign values to leaves of
# the segment tree
for i in range(n):
segtree[n + i] = a[i];
# assign values to remaining nodes
# to compute minimum in a given range
for i in range(n - 1, 0, -1):
segtree[i] = min(segtree[2 * i],
segtree[2 * i + 1])
def range_query(segtree, left, right, n):
left += n
right += n
""" Basically the left and right indices
will move towards right and left respectively
and with every each next higher level and
compute the minimum at each height change
the index to leaf node first """
mi = 1e9 # initialize minimum to a very high value
while (left < right):
if (left & 1): # if left index in odd
mi = min(mi, segtree[left])
left = left + 1
if (right & 1): # if right index in odd
right -= 1
mi = min(mi, segtree[right])
# move to the next higher level
left = left // 2
right = right // 2
return mi
def update(segtree, pos, value, n):
# change the index to leaf node first
pos += n
# update the value at the leaf node
# at the exact index
segtree[pos] = value
while (pos > 1):
# move up one level at a time in the tree
pos >>= 1;
# update the values in the nodes
# in the next higher level
segtree[pos] = min(segtree[2 * pos],
segtree[2 * pos + 1])
# Driver Code
# Elements in list
a = [2, 6, 10, 4, 7, 28, 9, 11, 6, 33]
n = len(a)
# Construct the segment tree by assigning
# the values to the internal nodes
segtree = [0 for i in range(2 * n)]
construct_segment_tree(segtree, a, n);
left = 0
right = 5 #compute minimum in the range left to right
print ("Minimum in range", left, "to", right, "is",
range_query(segtree, left, right + 1, n))
# update the value of index 3 to 1
index = 3
value = 1
# a[3] = 1;
# Contents of array : {2, 6, 10, 1, 7, 28, 9, 11, 6, 33}
update(segtree, index, value, n); # point update
left = 2
right = 6 # compute minimum in the range left to right
print("Minimum in range", left, "to", right, "is",
range_query(segtree, left, right + 1, n))
# This code is contributed by sarthak Raghuwanshi
C#
// C# Program to implement iterative segment
// tree.
using System;
class GFG
{
static void construct_segment_tree(int[] segtree,
int[] a, int n)
{
// assign values to leaves of the segment tree
for (int i = 0; i < n; i++)
segtree[n + i] = a[i];
/*
* assign values to internal nodes
* to compute minimum in a given range
*/
for (int i = n - 1; i >= 1; i--)
segtree[i] = Math.Min(segtree[2 * i],
segtree[2 * i + 1]);
}
static void update(int[] segtree, int pos,
int value, int n)
{
// change the index to leaf node first
pos += n;
// update the value at the leaf node
// at the exact index
segtree[pos] = value;
while (pos > 1)
{
// move up one level at a time in the tree
pos >>= 1;
// update the values in the nodes in
// the next higher level
segtree[pos] = Math.Min(segtree[2 * pos],
segtree[2 * pos + 1]);
}
}
static int range_query(int[] segtree, int left,
int right, int n)
{
/*
* Basically the left and right indices will move
* towards right and left respectively and with
* every each next higher level and compute the
* minimum at each height. */
// change the index to leaf node first
left += n;
right += n;
// initialize minimum to a very high value
int mi = (int) 1e9;
while (left < right)
{
// if left index in odd
if ((left & 1) == 1)
{
mi = Math.Min(mi, segtree[left]);
// make left index even
left++;
}
// if right index in odd
if ((right & 1) == 1)
{
// make right index even
right--;
mi = Math.Min(mi, segtree[right]);
}
// move to the next higher level
left /= 2;
right /= 2;
}
return mi;
}
// Driver Code
public static void Main(String[] args)
{
int[] a = {2, 6, 10, 4, 7, 28, 9, 11, 6, 33};
int n = a.Length;
/*
* Construct the segment tree by assigning
* the values to the internal nodes
*/
int[] segtree = new int[2 * n];
construct_segment_tree(segtree, a, n);
// compute minimum in the range left to right
int left = 0, right = 5;
Console.Write("Minimum in range {0} to {1} is {2}\n",
left, right, range_query(segtree,
left, right + 1, n));
// update the value of index 3 to 1
int index = 3, value = 1;
// a[3] = 1;
// Contents of array : {2, 6, 10, 1, 7, 28, 9, 11, 6, 33}
update(segtree, index, value, n); // point update
// compute minimum in the range left to right
left = 2;
right = 6;
Console.Write("Minimum in range {0} to {1} is {2}\n",
left, right, range_query(segtree,
left, right + 1, n));
}
}
// This code is contributed by Rajput-Ji
输出:
Minimum in range 0 to 5 is 2
Minimum in range 2 to 6 is 1
时间复杂度: (n log n)
辅助空间: (n)