Iterative Segment Tree (Range Maximum Query with Node Update)

Given an array arr[0 . . . n-1]. The task is to perform the following operation:

• Find the maximum of elements from index l to r where 0 <= l <= r <= n-1.
• Change value of a specified element of the array to a new value x. Given i and x, change A[i] to x, 0 <= i <= n-1.

Examples:

Input: a[] = {2, 6, 7, 5, 18, 86, 54, 2}
Query1: maximum(2, 7)
Query2: update(3, 90)
Query3: maximum(2, 6)
Output:
Maximum in range 2 to 7 is 86.
Maximum in range 2 to 6 is 90.

Recommended: Please try your approach on {IDE} first, before moving on to the solution.

We have discussed Recursive segment tree implementation. In this post, iterative implementation is discussed. The iterative version of the segment tree basically uses the fact, that for an index i, left child = 2 * i and right child = 2 * i + 1 in the tree. The parent for an index i in the segment tree array can be found by parent = i / 2. Thus we can easily travel up and down through the levels of the tree one by one. At first we compute the maximum in the ranges while constructing the tree starting from the leaf nodes and climbing up through the levels one by one. We use the same concept while processing the queries for finding the maximum in a range. Since there are (log n) levels in the worst case, so querying takes log n time. For update of a particular index to a given value we start updating the segment tree starting from the leaf nodes and update all those nodes which are affected by the updation of the current node by gradually moving up through the levels at every iteration. Updation also takes log n time because there we have to update all the levels starting from the leaf node where we update the exact value at the exact index given by the user.

Below is the implementation of the above approach.

 // 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 = 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; }

Output:

Maximum in range 1 to 5 is 28
Maximum in range 2 to 8 is 32

Time Complexity: (N * log N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

Article Tags :
Practice Tags :

Be the First to upvote.

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.