Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on Stack
  • Practice Stack
  • MCQs on Stack
  • Stack Tutorial
  • Stack Operations
  • Stack Implementations
  • Monotonic Stack
  • Infix to Postfix
  • Prefix to Postfix
  • Prefix to Infix
  • Advantages & Disadvantages
Open In App
Next Article:
Dynamic Segment Trees : Online Queries for Range Sum with Point Updates
Next article icon

Range Sum and Update in Array : Segment Tree using Stack

Last Updated : 09 Jan, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] of N integers. The task is to do the following operations: 
 

  1. Add a value X to all the element from index A to B where 0 ? A ? B ? N-1.
  2. Find the sum of the element from index L to R where 0 ? L ? R ? N-1 before and after the update given to the array above.

Example: 
 

Input: arr[] = {1, 3, 5, 7, 9, 11}, L = 1, R = 3, A = 1, B = 5, X = 10 
Output: 
Sum of values in given range = 15 
Updated sum of values in given range = 45 
Explanation: 
Sum of values in the range 1 to 3 is 3 + 5 + 7 = 15. 
arr[] after adding 10 from index 1 to 5 is arr[] = {1, 13, 15, 17, 19, 21} 
Sum of values in the range 1 to 3 after update is 13 + 15 + 17 = 45.
Input: arr[] = { 11, 32, 5, 7, 19, 11, 8}, L = 2, R = 6, A = 1, B = 5, X = 16 
Output: 
Sum of values in given range = 50 
Updated sum of values in given range = 114 
Explanation: 
Sum of values in the range 2 to 6 is 5 + 7 + 19 + 11 + 8 = 50. 
arr[] after adding 16 from index 1 to 5 is arr[] = {11, 48, 21, 23, 35, 27, 8} 
Sum of values in the range 2 to 6 after update is 21 + 23 + 35 + 27 + 8 = 114. 
 

 

Approach: 
The recursive approach using a Segment Tree for the given problem is discussed in this article. In this post we will discussed an approach using Stack Data Structure to avoid recursion. 
Below are the steps to implement Segment Tree using Stack: 
 

  1. The idea is to use tuple to store the state which has Node number and range indexes in the Stack.
  2. For Building Segment Tree: 
    • Push the root Node to the stack as a tuple: 
       
Stack S;
start = 0, end = arr_size - 1
S.emplace(1, start, end)

  • Pop the element from the stack and do the following until stack becomes empty: 
    1. If starting index equals to ending index, then we reach the leaf node and update the value at Segment tree array as value at current index in the given array.
    2. Else insert the flag tuple with the current Node as S.emplace(current_node, INF, INF) to inverse the order of evaluation and insert the tuple with value for left and right child as: 
       

mid = (start + end) / 2 
st.emplace(curr_node * 2, start, mid) 
st.emplace(curr_node * 2 + 1, mid + 1, end) 
 

  1. If start index and end index is same as INF, then update the Segment Tree value at current index as: 
     

Value at current index is updated as value at left child and right child: 
tree[curr_node] = tree[2*curr_node] + tree[2*curr_node + 1] 
 

  1. For Update Tree: 
    • Push the root node to the stack as done for building Segment Tree.
    • Pop the element from the stack and do the following until stack becomes empty: 
      1. If the current node has any pending update then first update to the current node.
      2. If the current node ranges lies completely in the update query range, then update the current node with that value.
      3. If the current node ranges overlap with the update query range, then follow the above approach and push the tuple for left child and right child in the Stack.
      4. Update the query using the result of left and right child above.
  2. For Update Query: 
    • Push the root node to the stack as done for building Segment Tree.
    • Pop the element from the stack and do the following until stack becomes empty: 
      1. If the current node ranges lies outside the given query, then continue with the next iteration.
      2. If the current node ranges lies completely in the update query range, then update the result with the current node value.
      3. If the current node ranges overlap with the update query range, then follow the above approach and push the tuple for left child and right child in the Stack.
      4. Update the result using the value obtained from left and right child Node.

Below is the implementation of the above approach:
 

CPP




#include "bits/stdc++.h"
using namespace std;
 
constexpr static int MAXSIZE = 1000;
constexpr static int INF = numeric_limits<int>::max();
 
// Segment Tree array
int64_t tree[MAXSIZE];
 
// Lazy Update array
int64_t lazy[MAXSIZE];
 
// This tuple will hold tree state
// the stacks
using QueryAdaptor = tuple<int64_t, int64_t, int64_t>;
 
// Build our segment tree
void build_tree(int64_t* arr, int64_t arr_size)
{
 
    // Stack will use to update
    // the tree value
    stack<QueryAdaptor> st;
 
    // Emplace the root of the tree
    st.emplace(1, 0, arr_size - 1);
 
    // Repeat until empty
    while (!st.empty()) {
 
        // Take the indexes at the
        // top of the stack
        int64_t currnode, curra, currb;
 
        // value at the top of the
        // stack
        tie(currnode, curra, currb) = st.top();
 
        // Pop the value from the
        // stack
        st.pop();
 
        // Flag with INF ranges are merged
        if (curra == INF && currb == INF) {
            tree[currnode] = tree[currnode * 2]
                             + tree[currnode * 2 + 1];
        }
 
        // Leaf node
        else if (curra == currb) {
            tree[currnode] = arr[curra];
        }
 
        else {
 
            // Insert flag node inverse
            // order of evaluation
            st.emplace(currnode, INF, INF);
            int64_t mid = (curra + currb) / 2;
 
            // Push children
            st.emplace(currnode * 2, curra, mid);
            st.emplace(currnode * 2 + 1, mid + 1, currb);
        }
    }
}
 
// A utility function that propagates
// updates lazily down the tree
inline void push_down(int64_t node, int64_t a, int64_t b)
{
    if (lazy[node] != 0) {
        tree[node] += lazy[node] * (b - a + 1);
 
        if (a != b) {
            lazy[2 * node] += lazy[node];
            lazy[2 * node + 1] += lazy[node];
        }
 
        lazy[node] = 0;
    }
}
 
// Iterative Range_Update function to
// add val to all elements in the
// range i-j (inclusive)
void update_tree(int64_t arr_size, int64_t i, int64_t j,
                 int64_t val)
{
 
    // Initialize the stack
    stack<QueryAdaptor> st;
 
    // Emplace the root of the tree
    st.emplace(1, 0, arr_size - 1);
 
    // Work until empty
    while (!st.empty()) {
 
        // Take the indexes at the
        // top of the stack
        int64_t currnode, curra, currb;
        tie(currnode, curra, currb) = st.top();
        st.pop();
 
        // Flag with INF ranges are merged
        if (curra == INF && currb == INF) {
            tree[currnode] = tree[currnode * 2]
                             + tree[currnode * 2 + 1];
        }
 
        // Traverse the previous updates
        // down the tree
        else {
            push_down(currnode, curra, currb);
 
            // No overlap condition
            if (curra > currb || curra > j || currb < i) {
                continue;
            }
 
            // Total overlap condition
            else if (curra >= i && currb <= j) {
 
                // Update lazy array
                tree[currnode] += val * (currb - curra + 1);
 
                if (curra != currb) {
                    lazy[currnode * 2] += val;
                    lazy[currnode * 2 + 1] += val;
                }
            }
 
            // Partial Overlap
            else {
 
                // Insert flag node inverse
                // order of evaluation
                st.emplace(currnode, INF, INF);
 
                int64_t mid = (curra + currb) / 2;
 
                // Push children
                st.emplace(currnode * 2, curra, mid);
                st.emplace(currnode * 2 + 1, mid + 1,
                           currb);
            }
        }
    }
}
 
// A function that find the sum of
// all elements in the range i-j
int64_t query(int64_t arr_size, int64_t i, int64_t j)
{
 
    // Initialize stack
    stack<QueryAdaptor> st;
 
    // Emplace root of the tree
    st.emplace(1, 0, arr_size - 1);
 
    int64_t result = 0;
 
    while (!st.empty()) {
 
        // Take the indexes at the
        // top of the stack
        int64_t currnode, curra, currb;
        tie(currnode, curra, currb) = st.top();
        st.pop();
 
        // Traverse the previous updates
        // down the tree
        push_down(currnode, curra, currb);
 
        // No overlap
        if (curra > currb || curra > j || currb < i) {
            continue;
        }
 
        // Total Overlap
        else if (curra >= i && currb <= j) {
            result += tree[currnode];
        }
 
        // Partial Overlap
        else {
            std::int64_t mid = (curra + currb) / 2;
 
            // Push children
            st.emplace(currnode * 2, curra, mid);
            st.emplace(currnode * 2 + 1, mid + 1, currb);
        }
    }
 
    return result;
}
 
// Driver Code
int main()
{
 
    // Initialize our trees with 0
    memset(tree, 0, sizeof(int64_t) * MAXSIZE);
    memset(lazy, 0, sizeof(int64_t) * MAXSIZE);
 
    int64_t arr[] = { 1, 3, 5, 7, 9, 11 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Build segment tree from given array
    build_tree(arr, n);
 
    // Print sum of values in array
    // from index 1 to 3
    cout << "Sum of values in given range = "
         << query(n, 1, 3) << endl;
 
    // Add 10 to all nodes at indexes
    // from 1 to 5
    update_tree(n, 1, 5, 10);
 
    // Find sum after the value is updated
    cout << "Updated sum of values in given range = "
         << query(n, 1, 3) << endl;
 
    return 0;
}
 
 

Java




// Java implementation of the approach
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
class GFG {
 
    static final int MAXSIZE = 1000;
    static final int INF = (int)Double.POSITIVE_INFINITY;
 
    // Segment Tree array
    static int[] tree = new int[MAXSIZE];
 
    // Lazy Update array
    static int[] lazy = new int[MAXSIZE];
 
    // Build our segment tree
    static void build_tree(int[] arr, int arr_size)
    {
 
        // Stack will use to update
        // the tree value
        Stack<List<Integer> > st = new Stack<>();
 
        // push the root of the tree
        st.push(Arrays.asList(1, 0, arr_size - 1));
 
        // Repeat until empty
        while (!st.isEmpty()) {
 
            // Take the indexes at the
            // top of the stack
            int currnode, curra, currb;
 
            // value at the top of the
            // stack
            List<Integer> temp = st.peek();
            currnode = temp.get(0);
            curra = temp.get(1);
            currb = temp.get(2);
 
            // Pop the value from the
            // stack
            st.pop();
 
            // Flag with INF ranges are merged
            if (curra == INF && currb == INF) {
                tree[currnode] = tree[currnode * 2]
                                 + tree[currnode * 2 + 1];
            }
 
            // Leaf node
            else if (curra == currb) {
                tree[currnode] = arr[curra];
            }
 
            else {
 
                // Insert flag node inverse
                // order of evaluation
                st.push(Arrays.asList(currnode, INF, INF));
 
                int mid = (curra + currb) / 2;
 
                // Push children
                st.push(Arrays.asList(currnode * 2, curra,
                                      mid));
                st.push(Arrays.asList(currnode * 2 + 1,
                                      mid + 1, currb));
            }
        }
    }
 
    // A utility function that propagates
    // updates lazily down the tree
    static void push_down(int node, int a, int b)
    {
        if (lazy[node] != 0) {
            tree[node] += lazy[node] * (b - a + 1);
 
            if (a != b) {
                lazy[2 * node] += lazy[node];
                lazy[2 * node + 1] += lazy[node];
            }
 
            lazy[node] = 0;
        }
    }
 
    // Iterative Range_Update function to
    // add val to all elements in the
    // range i-j (inclusive)
    static void update_tree(int arr_size, int i, int j,
                            int val)
    {
 
        // Initialize the stack
        Stack<List<Integer> > st = new Stack<>();
 
        // push the root of the tree
        st.push(Arrays.asList(1, 0, arr_size - 1));
 
        // Work until empty
        while (!st.isEmpty()) {
 
            // Take the indexes at the
            // top of the stack
            int currnode, curra, currb;
            List<Integer> temp = st.peek();
            currnode = temp.get(0);
            curra = temp.get(1);
            currb = temp.get(2);
            st.pop();
 
            // Flag with INF ranges are merged
            if (curra == INF && currb == INF) {
                tree[currnode] = tree[currnode * 2]
                                 + tree[currnode * 2 + 1];
            }
 
            // Traverse the previous updates
            // down the tree
            else {
                push_down(currnode, curra, currb);
 
                // No overlap condition
                if (curra > currb || curra > j
                    || currb < i) {
                    continue;
                }
 
                // Total overlap condition
                else if (curra >= i && currb <= j) {
 
                    // Update lazy array
                    tree[currnode]
                        += val * (currb - curra + 1);
 
                    if (curra != currb) {
                        lazy[currnode * 2] += val;
                        lazy[currnode * 2 + 1] += val;
                    }
                }
 
                // Partial Overlap
                else {
 
                    // Insert flag node inverse
                    // order of evaluation
                    st.push(
                        Arrays.asList(currnode, INF, INF));
 
                    int mid = (curra + currb) / 2;
 
                    // Push children
                    st.push(Arrays.asList(currnode * 2,
                                          curra, mid));
                    st.push(Arrays.asList(currnode * 2 + 1,
                                          mid + 1, currb));
                }
            }
        }
    }
 
    // A function that find the sum of
    // all elements in the range i-j
    static int query(int arr_size, int i, int j)
    {
 
        // Initialize stack
        Stack<List<Integer> > st = new Stack<>();
 
        // push root of the tree
        st.push(Arrays.asList(1, 0, arr_size - 1));
 
        int result = 0;
 
        while (!st.isEmpty()) {
 
            // Take the indexes at the
            // top of the stack
            int currnode, curra, currb;
            List<Integer> temp = st.peek();
            currnode = temp.get(0);
            curra = temp.get(1);
            currb = temp.get(2);
            st.pop();
 
            // Traverse the previous updates
            // down the tree
            push_down(currnode, curra, currb);
 
            // No overlap
            if (curra > currb || curra > j || currb < i) {
                continue;
            }
 
            // Total Overlap
            else if (curra >= i && currb <= j) {
                result += tree[currnode];
            }
 
            // Partial Overlap
            else {
                int mid = (curra + currb) / 2;
 
                // Push children
                st.push(Arrays.asList(currnode * 2, curra,
                                      mid));
                st.push(Arrays.asList(currnode * 2 + 1,
                                      mid + 1, currb));
            }
        }
 
        return result;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
 
        // Initialize our trees with 0
        Arrays.fill(tree, 0);
        Arrays.fill(lazy, 0);
 
        int arr[] = { 1, 3, 5, 7, 9, 11 };
        int n = arr.length;
 
        // Build segment tree from given array
        build_tree(arr, n);
 
        // Print sum of values in array
        // from index 1 to 3
        System.out.printf(
            "Sum of values in given range = %d\n",
            query(n, 1, 3));
 
        // Add 10 to all nodes at indexes
        // from 1 to 5
        update_tree(n, 1, 5, 10);
 
        // Find sum after the value is updated
        System.out.printf(
            "Updated sum of values in given range = %d\n",
            query(n, 1, 3));
    }
}
 
// This code is contributed by sanjeev2552
 
 

Python3




MAXSIZE = 1000
INF = float('inf')
 
# Segment Tree array
tree = [0] * MAXSIZE
 
# Lazy Update array
lazy = [0] * MAXSIZE
 
# This tuple will hold tree state
# the stacks
QueryAdaptor = (int, int, int)
 
# Build our segment tree
 
 
def build_tree(arr, arr_size):
    st = []
    st.append((1, 0, arr_size - 1))
 
    while st:
        currnode, curra, currb = st.pop()
 
        if curra == INF and currb == INF:
            tree[currnode] = tree[currnode * 2] + tree[currnode * 2 + 1]
        elif curra == currb:
            tree[currnode] = arr[curra]
        else:
            st.append((currnode, INF, INF))
            mid = (curra + currb) // 2
            st.append((currnode * 2, curra, mid))
            st.append((currnode * 2 + 1, mid + 1, currb))
 
# A utility function that propagates
# updates lazily down the tree
 
 
def push_down(node, a, b):
    if lazy[node] != 0:
        tree[node] += lazy[node] * (b - a + 1)
 
        if a != b:
            lazy[2 * node] += lazy[node]
            lazy[2 * node + 1] += lazy[node]
 
        lazy[node] = 0
 
# Iterative Range_Update function to
# add val to all elements in the
# range i-j (inclusive)
 
 
def update_tree(arr_size, i, j, val):
    st = []
    st.append((1, 0, arr_size - 1))
 
    while st:
        currnode, curra, currb = st.pop()
 
        if curra == INF and currb == INF:
            tree[currnode] = tree[currnode * 2] + tree[currnode * 2 + 1]
        else:
            push_down(currnode, curra, currb)
 
            if curra > currb or curra > j or currb < i:
                continue
            elif curra >= i and currb <= j:
                tree[currnode] += val * (currb - curra + 1)
 
                if curra != currb:
                    lazy[currnode * 2] += val
                    lazy[currnode * 2 + 1] += val
            else:
                st.append((currnode, INF, INF))
                mid = (curra + currb) // 2
                st.append((currnode * 2, curra, mid))
                st.append((currnode * 2 + 1, mid + 1, currb))
 
# A function that finds the sum of
# all elements in the range i-j
 
 
def query(arr_size, i, j):
    st = []
    st.append((1, 0, arr_size - 1))
    result = 0
 
    while st:
        currnode, curra, currb = st.pop()
 
        push_down(currnode, curra, currb)
 
        if curra > currb or curra > j or currb < i:
            continue
        elif curra >= i and currb <= j:
            result += tree[currnode]
        else:
            mid = (curra + currb) // 2
            st.append((currnode * 2, curra, mid))
            st.append((currnode * 2 + 1, mid + 1, currb))
 
    return result
 
# Driver Code
 
 
def main():
    global tree, lazy
 
    # Initialize our trees with 0
    tree = [0] * MAXSIZE
    lazy = [0] * MAXSIZE
 
    arr = [1, 3, 5, 7, 9, 11]
    n = len(arr)
 
    # Build segment tree from given array
    build_tree(arr, n)
 
    # Print sum of values in array
    # from index 1 to 3
    print("Sum of values in given range =", query(n, 1, 3))
 
    # Add 10 to all nodes at indexes
    # from 1 to 5
    update_tree(n, 1, 5, 10)
 
    # Find sum after the value is updated
    print("Updated sum of values in given range =", query(n, 1, 3))
 
 
if __name__ == "__main__":
    main()
 
# This code is contributed by arindam369
 
 

C#




using System;
using System.Collections.Generic;
 
class SegmentTree
{
    const int MAXSIZE = 1000;
    const long INF = long.MaxValue;
 
    static long[] tree = new long[MAXSIZE];
    static long[] lazy = new long[MAXSIZE];
 
    // Build our segment tree
    static void BuildTree(long[] arr, int arrSize)
    {
        Stack<(long, long, long)> st = new Stack<(long, long, long)>();
        st.Push((1, 0, arrSize - 1));
 
        while (st.Count > 0)
        {
            (long currNode, long curra, long currb) = st.Pop();
 
            if (curra == INF && currb == INF)
                tree[currNode] = tree[currNode * 2] + tree[currNode * 2 + 1];
            else if (curra == currb)
                tree[currNode] = arr[curra];
            else
            {
                st.Push((currNode, INF, INF));
                long mid = (curra + currb) / 2;
                st.Push((currNode * 2, curra, mid));
                st.Push((currNode * 2 + 1, mid + 1, currb));
            }
        }
    }
 
    // A utility function that propagates
    // updates lazily down the tree
    static void PushDown(long node, long a, long b)
    {
        if (lazy[node] != 0)
        {
            tree[node] += lazy[node] * (b - a + 1);
 
            if (a != b)
            {
                lazy[2 * node] += lazy[node];
                lazy[2 * node + 1] += lazy[node];
            }
 
            lazy[node] = 0;
        }
    }
 
    // Iterative Range_Update function to
    // add val to all elements in the
    // range i-j (inclusive)
    static void UpdateTree(int arrSize, long i, long j, long val)
    {
        Stack<(long, long, long)> st = new Stack<(long, long, long)>();
        st.Push((1, 0, arrSize - 1));
 
        while (st.Count > 0)
        {
            (long currNode, long curra, long currb) = st.Pop();
 
            if (curra == INF && currb == INF)
                tree[currNode] = tree[currNode * 2] + tree[currNode * 2 + 1];
            else
            {
                PushDown(currNode, curra, currb);
 
                if (curra > currb || curra > j || currb < i)
                    continue;
                else if (curra >= i && currb <= j)
                {
                    tree[currNode] += val * (currb - curra + 1);
 
                    if (curra != currb)
                    {
                        lazy[currNode * 2] += val;
                        lazy[currNode * 2 + 1] += val;
                    }
                }
                else
                {
                    st.Push((currNode, INF, INF));
                    long mid = (curra + currb) / 2;
                    st.Push((currNode * 2, curra, mid));
                    st.Push((currNode * 2 + 1, mid + 1, currb));
                }
            }
        }
    }
 
    // A function that finds the sum of
    // all elements in the range i-j
    static long Query(int arrSize, long i, long j)
    {
        Stack<(long, long, long)> st = new Stack<(long, long, long)>();
        st.Push((1, 0, arrSize - 1));
        long result = 0;
 
        while (st.Count > 0)
        {
            (long currNode, long curra, long currb) = st.Pop();
 
            PushDown(currNode, curra, currb);
 
            if (curra > currb || curra > j || currb < i)
                continue;
            else if (curra >= i && currb <= j)
                result += tree[currNode];
            else
            {
                long mid = (curra + currb) / 2;
                st.Push((currNode * 2, curra, mid));
                st.Push((currNode * 2 + 1, mid + 1, currb));
            }
        }
 
        return result;
    }
 
    // Driver Code
    static void Main()
    {
        // Initialize our trees with 0
        Array.Clear(tree, 0, MAXSIZE);
        Array.Clear(lazy, 0, MAXSIZE);
 
        long[] arr = { 1, 3, 5, 7, 9, 11 };
        int n = arr.Length;
 
        // Build segment tree from given array
        BuildTree(arr, n);
 
        // Print sum of values in array
        // from index 1 to 3
        Console.WriteLine("Sum of values in given range = " + Query(n, 1, 3));
 
        // Add 10 to all nodes at indexes
        // from 1 to 5
        UpdateTree(n, 1, 5, 10);
 
        // Find sum after the value is updated
        Console.WriteLine("Updated sum of values in given range = " + Query(n, 1, 3));
    }
}
 
 

Javascript




const MAXSIZE = 1000;
const INF = Number.MAX_SAFE_INTEGER;
 
// Segment Tree array
let tree = Array(MAXSIZE).fill(0);
 
// Lazy Update array
let lazy = Array(MAXSIZE).fill(0);
 
// This tuple will hold tree state
// the stacks
// Using an array instead of a tuple
// since JavaScript does not have built-in tuple support
// [currnode, curra, currb]
let QueryAdaptor;
 
// Build our segment tree
function build_tree(arr, arr_size) {
    // Stack will use to update
    // the tree value
    let st = [];
 
    // Emplace the root of the tree
    st.push([1, 0, arr_size - 1]);
 
    // Repeat until empty
    while (st.length > 0) {
        // Take the indexes at the
        // top of the stack
        let [currnode, curra, currb] = st.pop();
 
        // Flag with INF ranges are merged
        if (curra === INF && currb === INF) {
            tree[currnode] = tree[currnode * 2] + tree[currnode * 2 + 1];
        }
        // Leaf node
        else if (curra === currb) {
            tree[currnode] = arr[curra];
        } else {
            // Insert flag node inverse
            // order of evaluation
            st.push([currnode, INF, INF]);
            let mid = Math.floor((curra + currb) / 2);
 
            // Push children
            st.push([currnode * 2, curra, mid]);
            st.push([currnode * 2 + 1, mid + 1, currb]);
        }
    }
}
 
// A utility function that propagates
// updates lazily down the tree
function push_down(node, a, b) {
    if (lazy[node] !== 0) {
        tree[node] += lazy[node] * (b - a + 1);
 
        if (a !== b) {
            lazy[2 * node] += lazy[node];
            lazy[2 * node + 1] += lazy[node];
        }
 
        lazy[node] = 0;
    }
}
 
// Iterative Range_Update function to
// add val to all elements in the
// range i-j (inclusive)
function update_tree(arr_size, i, j, val) {
    // Initialize the stack
    let st = [];
 
    // Emplace the root of the tree
    st.push([1, 0, arr_size - 1]);
 
    // Work until empty
    while (st.length > 0) {
        // Take the indexes at the
        // top of the stack
        let [currnode, curra, currb] = st.pop();
 
        // Flag with INF ranges are merged
        if (curra === INF && currb === INF) {
            tree[currnode] = tree[currnode * 2] + tree[currnode * 2 + 1];
        } else {
            push_down(currnode, curra, currb);
 
            // No overlap condition
            if (curra > currb || curra > j || currb < i) {
                continue;
            }
            // Total overlap condition
            else if (curra >= i && currb <= j) {
                // Update lazy array
                tree[currnode] += val * (currb - curra + 1);
 
                if (curra !== currb) {
                    lazy[currnode * 2] += val;
                    lazy[currnode * 2 + 1] += val;
                }
            }
            // Partial Overlap
            else {
                // Insert flag node inverse
                // order of evaluation
                st.push([currnode, INF, INF]);
                let mid = Math.floor((curra + currb) / 2);
 
                // Push children
                st.push([currnode * 2, curra, mid]);
                st.push([currnode * 2 + 1, mid + 1, currb]);
            }
        }
    }
}
 
// A function that find the sum of
// all elements in the range i-j
function query(arr_size, i, j) {
    // Initialize stack
    let st = [];
 
    // Emplace root of the tree
    st.push([1, 0, arr_size - 1]);
 
    let result = 0;
 
    while (st.length > 0) {
        // Take the indexes at the
        // top of the stack
        let [currnode, curra, currb] = st.pop();
 
        // Traverse the previous updates
        // down the tree
        push_down(currnode, curra, currb);
 
        // No overlap
        if (curra > currb || curra > j || currb < i) {
            continue;
        }
        // Total Overlap
        else if (curra >= i && currb <= j) {
            result += tree[currnode];
        }
        // Partial Overlap
        else {
            let mid = Math.floor((curra + currb) / 2);
 
            // Push children
            st.push([currnode * 2, curra, mid]);
            st.push([currnode * 2 + 1, mid + 1, currb]);
        }
    }
 
    return result;
}
 
// Driver Code
// Initialize our trees with 0
tree.fill(0);
lazy.fill(0);
 
let arr = [1, 3, 5, 7, 9, 11];
let n = arr.length;
 
// Build segment tree from given array
build_tree(arr, n);
 
// Print sum of values in array
// from index 1 to 3
console.log("Sum of values in given range =", query(n, 1, 3));
 
// Add 10 to all nodes at indexes
// from 1 to 5
update_tree(n, 1, 5, 10);
 
// Find sum after the value is updated
console.log("Updated sum of values in given range =", query(n, 1, 3));
 
 
Output
Sum of values in given range = 15 Updated sum of values in given range = 45      

Time Complexity: 
 

  • For Tree Construction: O(N), There are (2n-1) nodes in the tree and value of every node is calculated once.
  • For Query: O(log N), To query a sum we processed atmost four nodes at every level and number of level is log N.
  • For Update: O(log N), To update the tree with lazy propagation is O(Log N) as we update the root of the tree and then update only that part of the tree whose ranges overlaps at each level.

 

Related Topic: Segment Tree



Next Article
Dynamic Segment Trees : Online Queries for Range Sum with Point Updates

P

phoemur
Improve
Article Tags :
  • Advanced Data Structure
  • DSA
  • Stack
  • Tree
  • Segment-Tree
Practice Tags :
  • Advanced Data Structure
  • Segment-Tree
  • Stack
  • Tree

Similar Reads

  • Segment Tree
    Segment Tree is a data structures that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tre
    3 min read
  • Segment tree meaning in DSA
    A segment tree is a data structure used to effectively query and update ranges of array members. It's typically implemented as a binary tree, with each node representing a segment or range of array elements. Characteristics of Segment Tree:A segment tree is a binary tree with a leaf node for each el
    2 min read
  • Introduction to Segment Trees - Data Structure and Algorithm Tutorials
    A Segment Tree is used to stores information about array intervals in its nodes. It allows efficient range queries over array intervals.Along with queries, it allows efficient updates of array items.For example, we can perform a range summation of an array between the range L to R in O(Log n) while
    15+ min read
  • Persistent Segment Tree | Set 1 (Introduction)
    Prerequisite : Segment Tree Persistency in Data Structure Segment Tree is itself a great data structure that comes into play in many cases. In this post we will introduce the concept of Persistency in this data structure. Persistency, simply means to retain the changes. But obviously, retaining the
    15+ min read
  • Segment tree | Efficient implementation
    Let us consider the following problem to understand Segment Trees without recursion.We have an array arr[0 . . . n-1]. We should be able to, Find the sum of elements from index l to r where 0 <= l <= r <= n-1Change the value of a specified element of the array to a new value x. We need to d
    12 min read
  • 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:
    14 min read
  • Range Sum and Update in Array : Segment Tree using Stack
    Given an array arr[] of N integers. The task is to do the following operations: Add a value X to all the element from index A to B where 0 ? A ? B ? N-1.Find the sum of the element from index L to R where 0 ? L ? R ? N-1 before and after the update given to the array above.Example: Input: arr[] = {1
    15+ min read
  • Dynamic Segment Trees : Online Queries for Range Sum with Point Updates
    Prerequisites: Segment TreeGiven a number N which represents the size of the array initialized to 0 and Q queries to process where there are two types of queries: 1 P V: Put the value V at position P.2 L R: Output the sum of values from L to R. The task is to answer these queries. Constraints: 1 ? N
    15+ min read
  • Applications, Advantages and Disadvantages of Segment Tree
    First, let us understand why we need it prior to landing on the introduction so as to get why this concept was introduced. Suppose we are given an array and we need to find out the subarray Purpose of Segment Trees: A segment tree is a data structure that deals with a range of queries over an array.
    4 min read
  • Lazy Propagation

    • Lazy Propagation in Segment Tree
      Segment tree is introduced in previous post with an example of range sum problem. We have used the same "Sum of given Range" problem to explain Lazy propagation How does update work in Simple Segment Tree? In the previous post, update function was called to update only a single value in array. Pleas
      15+ min read

    • Lazy Propagation in Segment Tree | Set 2
      Given an array arr[] of size N. There are two types of operations: Update(l, r, x) : Increment the a[i] (l <= i <= r) with value x.Query(l, r) : Find the maximum value in the array in a range l to r (both are included).Examples: Input: arr[] = {1, 2, 3, 4, 5} Update(0, 3, 4) Query(1, 4) Output
      15+ min read

    • Flipping Sign Problem | Lazy Propagation Segment Tree
      Given an array of size N. There can be multiple queries of the following types. update(l, r) : On update, flip( multiply a[i] by -1) the value of a[i] where l <= i <= r . In simple terms, change the sign of a[i] for the given range.query(l, r): On query, print the sum of the array in given ran
      15+ min read

geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences