📌  相关文章
📜  迭代段树(带有节点更新的范围最大查询)

📅  最后修改于: 2021-04-17 09:21:05             🧑  作者: Mango

给定数组arr [0。 。 。 n-1]。任务是执行以下操作:

  • 查找从索引l到r的元素的最大值,其中0 <= l <= r <= n-1。
  • 将数组的指定元素的值更改为新值x。给定i和x,将A [i]更改为x,0 <= i <= n-1。

例子:

我们已经讨论了递归段树的实现。在这篇文章中,讨论了迭代实现。段树的迭代版本主要使用以下事实:对于索引i,树中的左子节点= 2 * i,右子节点= 2 * i + 1。可以通过parent = i / 2找到分段树数组中索引i的父级。因此,我们可以轻松地在树的各个层次上上下移动。首先,我们计算范围内的最大值,同时构造从叶节点开始并逐层爬升的树。在处理查询以查找范围内的最大值时,我们使用相同的概念。由于在最坏的情况下有(log n)个级别,因此查询花费log n时间。为了将特定索引更新为给定值,我们开始从叶节点开始更新段树,并通过在每次迭代中逐步上移级别来更新受当前节点更新影响的所有那些节点。更新也需要花费n倍的时间,因为我们必须从叶节点开始更新所有级别,在该叶节点处,我们将根据用户指定的确切索引来更新确切值。

下面是上述方法的实现。

C++
// C++ Program to implement
// iterative segment tree.
#include 
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 maximum in a given range */
    for (int i = n - 1; i >= 1; i--)
        segtree[i] = max(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] = max(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 
        maximum at each height. */
    // change the index to leaf node first
    left += n;
    right += n;
  
    // initialize maximum to a very low value
    int ma = INT_MIN;
  
    while (left < right) {
  
        // if left index in odd
        if (left & 1) {
            ma = max(ma, segtree[left]);
  
            // make left index even
            left++;
        }
  
        // if right index in odd
        if (right & 1) {
  
            // make right index even
            right--;
  
            ma = max(ma, segtree[right]);
        }
  
        // move to the next higher level
        left /= 2;
        right /= 2;
    }
    return ma;
}
  
// 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 maximum in the range left to right
    int left = 1, right = 5;
    cout << "Maximum in range " << left << " to "
         << right << " is " << range_query(segtree, left,
                                           right + 1, n)
         << "\n";
  
    // update the value of index 5 to 32
    int index = 5, value = 32;
  
    // a[5] = 32;
    // Contents of array : {2, 6, 10, 4, 7, 32, 9, 11, 6, 33}
    update(segtree, index, value, n);
  
    // compute maximum in the range left to right
    left = 2, right = 8;
    cout << "Maximum in range " << left << " to "
         << right << " is " << range_query(segtree,
                                           left, right + 1, n)
         << "\n";
  
    return 0;
}


Python3
# Python Program to implement
# iterative segment tree.
  
from sys import maxsize
INT_MIN = -maxsize
  
def construct_segment_tree(a: list, n: int):
    global segtree
  
    # assign values to leaves of the segment tree
    for i in range(n):
        segtree[n + i] = a[i]
  
    # assign values to internal nodes
    # to compute maximum in a given range */
    for i in range(n - 1, 0, -1):
        segtree[i] = max(segtree[2 * i], segtree[2 * i + 1])
  
def update(pos: int, value: int, n: int):
    global segtree
  
    # 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 //= 2
  
        # update the values in the nodes in
        # the next higher level
        segtree[pos] = max(segtree[2 * pos], segtree[2 * pos + 1])
  
def range_query(left: int, right: int, n: int) -> int:
    global segtree
  
    # Basically the left and right indices will move
    # towards right and left respectively and with
    # every each next higher level and compute the
    # maximum at each height.
    # change the index to leaf node first
    left += n
    right += n
  
    # initialize maximum to a very low value
    ma = INT_MIN
    while left < right:
  
        # if left index in odd
        if left & 1:
            ma = max(ma, segtree[left])
  
            # make left index even
            left += 1
  
        # if right index in odd
        if right & 1:
  
            # make right index even
            right -= 1
  
            ma = max(ma, segtree[right])
  
        # move to the next higher level
        left //= 2
        right //= 2
    return ma
  
  
# Driver Code
if __name__ == "__main__":
    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] * (2 * n)
    construct_segment_tree(a, n)
  
    # compute maximum in the range left to right
    left = 1
    right = 5
    print("Maximum in range %d to %d is %d" %
        (left, right, range_query(left, right + 1, n)))
  
    # update the value of index 5 to 32
    index = 5
    value = 32
  
    # a[5] = 32;
    # Contents of array : {2, 6, 10, 4, 7, 32, 9, 11, 6, 33}
    update(index, value, n)
  
    # compute maximum in the range left to right
    left = 2
    right = 8
    print("Maximum in range %d to %d is %d" %
        (left, right, range_query(left, right + 1, n)))
  
# This code is contributed by
# sanjeev2552


输出:
Maximum in range 1 to 5 is 28
Maximum in range 2 to 8 is 32

时间复杂度: (N * log N)
辅助空间: O(N)