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 Tree
  • Practice Tree
  • MCQs on Tree
  • Tutorial on Tree
  • Types of Trees
  • Basic operations
  • Tree Traversal
  • Binary Tree
  • Complete Binary Tree
  • Ternary Tree
  • Binary Search Tree
  • Red-Black Tree
  • AVL Tree
  • Full Binary Tree
  • B-Tree
  • Advantages & Disadvantages
Open In App
Next Article:
Persistent Segment Tree | Set 1 (Introduction)
Next article icon

Introduction to Segment Trees – Data Structure and Algorithm Tutorials

Last Updated : 14 Dec, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

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 also modifying any array element in O(Log n) Time

Types of Operations:

Segment Trees are mainly used for range queries on a fixed sized array. The values of array elements can be changed. The type of range queries that a segment tree can perform must have the property that to answer query from L to R, we can use the answers from L to M and M + 1 to R where M is a point between L to R, i.e., L <= M <= R.

The following are few example queries over a range in an array.

  • Addition/Subtraction
  • Maximum/Minimum
  • GCD/LCM
  • AND/OR/XOR

Structure of the Tree

The segment tree works on the principle of divide and conquer. 

  • At each level, we divide the array segments into two parts. If the given array had [0, . . ., N-1] elements in it then the two parts of the array will be [0, . . ., N/2-1] and [N/2, . . ., N-1]. 
  • We will then recursively go on until the lower and upper bounds of the range become equal. 
  • The structure of the segment tree looks like a binary tree.

The segment tree is generally represented using an array where the first value stores the value for the total array range and the child of the node at the ith index are at (2*i + 1) and (2*i + 2).

Constructing the segment tree:

There are two important points to be noted while constructing the segment tree:

  • Choosing what value to be stored in the nodes according to the problem definition
  • What should the merge operation do

If the problem definition states that we need to calculate the sum over ranges, then the value at nodes should store the sum of values over the ranges.

  • The child node values are merged back into the parent node to hold the value for that particular range, [i.e., the range covered by all the nodes of its subtree]. 
  • In the end, leaf nodes store information about a single element. All the leaf nodes store the array based on which the segment tree is built. 

Following are the steps for constructing a segment tree:

  1. Start from the leaves of the tree
  2. Recursively build the parents from the merge operation

The merge operation will take constant time if the operator takes constant time. SO building the whole tree takes O(N) time.

Segment tree

Range Query

Let us understand this with the help of the following problem

Given two integers L and R return the sum of the segment [L, R]

The first step is constructing the segment tree with the addition operator and 0 as the neutral element. 

  • If the range is one of the node’s range values then simply return the answer.
  • Otherwise, we will need to traverse the left and right children of the nodes and recursively continue the process till we find a node that covers a range that totally covers a part or whole of the range [L, R]
  • While returning from each call, we need to merge the answers received from each of its child.

As the height of the segment tree is logN the query time will be O(logN) per query.

Range Query in Segment Tree

Range Query in Segment Tree

Point Updates

Given an index,  idx, update the value of the array at index idx with value V

The element’s contribution is only in the path from its leaf to its parent. Thus only logN elements will get affected due to the update.

For updating, traverse till the leaf that stores the value of index idx and update the value. Then while tracing back in the path, modify the ranges accordingly. 

The time complexity will be O(logN).

Point Update in Segment Tree

Point Update in Segment Tree

Below is the implementation of construction, query, and point update for a segment tree:

C++
// C++ code for segment tree with sum // range and update query  #include <bits/stdc++.h> using namespace std; vector<int> A, ST;  void build(int node, int L, int R) {      // Leaf node where L == R     if (L == R) {         ST[node] = A[L];     }     else {          // Find the middle element to         // split the array into two halves         int mid = (L + R) / 2;          // Recursively travel the         // left half         build(2 * node, L, mid);          // Recursively travel the         // right half         build(2 * node + 1, mid + 1, R);          // Storing the sum of both the         // children into the parent         ST[node] = ST[2 * node] + ST[2 * node + 1];     } }  void update(int node, int L, int R, int idx, int val) {      // Find the lead node and     // update its value     if (L == R) {         A[idx] += val;         ST[node] += val;     }     else {          // Find the mid         int mid = (L + R) / 2;          // If node value idx is at the         // left part then update         // the left part         if (L <= idx and idx <= mid)             update(2 * node, L, mid, idx, val);         else             update(2 * node + 1, mid + 1, R, idx, val);          // Store the information in parents         ST[node] = ST[2 * node] + ST[2 * node + 1];     } }  int query(int node, int tl, int tr, int l, int r) {      // If it lies out of range then     // return 0     if (r < tl or tr < l)         return 0;      // If the node contains the range then     // return the node value     if (l <= tl and tr <= r)         return ST[node];     int tm = (tl + tr) / 2;      // Recursively traverse left and right     // and find the node     return query(2 * node, tl, tm, l, r)            + query(2 * node + 1, tm + 1, tr, l, r); }  // Driver code int main() {     int n = 6;     A = { 0, 1, 3, 5, -2, 3 };      // Create a segment tree of size 4*n     ST.resize(4 * n);      // Build a segment tree     build(1, 0, n - 1);     cout << "Sum of values in range 0-4 are: "          << query(1, 0, n - 1, 0, 4) << "\n";      // Update the value at idx = 1 by     // 100 thus becoming 101     update(1, 0, n - 1, 1, 100);     cout << "Value at index 1 increased by 100\n";     cout << "sum of value in range 1-3 are: "          << query(1, 0, n - 1, 1, 3) << "\n";      return 0; } 
Java
// Java code for segment tree with sum // range and update query import java.io.*; import java.util.*;  class GFG {     static int n = 6;     static int A[] = { 0, 1, 3, 5, -2, 3 };      // Create a segment tree of size 4*n     static int ST[] = new int[4 * n];     public static void build(int node, int L, int R)     {          // Leaf node where L == R         if (L == R) {             ST[node] = A[L];         }         else {              // Find the middle element to             // split the array into two halves             int mid = (L + R) / 2;              // Recursively travel the             // left half             build(2 * node, L, mid);              // Recursively travel the             // right half             build(2 * node + 1, mid + 1, R);              // Storing the sum of both the             // children into the parent             ST[node] = ST[2 * node] + ST[2 * node + 1];         }     }      public static void update(int node, int L, int R,                               int idx, int val)     {          // Find the lead node and         // update its value         if (L == R) {             A[idx] += val;             ST[node] += val;         }         else {              // Find the mid             int mid = (L + R) / 2;              // If node value idx is at the             // left part then update             // the left part             if (L <= idx && idx <= mid)                 update(2 * node, L, mid, idx, val);             else                 update(2 * node + 1, mid + 1, R, idx, val);              // Store the information in parents             ST[node] = ST[2 * node] + ST[2 * node + 1];         }     }      public static int query(int node, int tl, int tr, int l,                             int r)     {          // If it lies out of range then         // return 0         if (r < tl || tr < l)             return 0;          // If the node contains the range then         // return the node value         if (l <= tl && tr <= r)             return ST[node];         int tm = (tl + tr) / 2;          // Recursively traverse left and right         // and find the node         return query(2 * node, tl, tm, l, r)             + query(2 * node + 1, tm + 1, tr, l, r);     }      // Driver Code     public static void main(String[] args)     {         // Build a segment tree         build(1, 0, n - 1);         System.out.println(             "Sum of values in range 0-4 are: "             + query(1, 0, n - 1, 0, 4));          // Update the value at idx = 1 by         // 100 ths becoming 101         update(1, 0, n - 1, 1, 100);         System.out.println(             "Value at index 1 increased by 100");         System.out.println("sum of value in range 1-3 are: "                            + query(1, 0, n - 1, 1, 3));     } }  // This code is contributed by Rohit Pradhan 
Python
# python3 code for segment tree with sum # range and update query A = [] ST = []   def build(node, L, R):     global A, ST      # Leaf node where L == R     if (L == R):         ST[node] = A[L]      else:          # Find the middle element to         # split the array into two halves         mid = (L + R) // 2          # Recursively travel the         # left half         build(2 * node, L, mid)          # Recursively travel the         # right half         build(2 * node + 1, mid + 1, R)          # Storing the sum of both the         # children into the parent         ST[node] = ST[2 * node] + ST[2 * node + 1]   def update(node, L, R, idx, val):     global A, ST      # Find the lead node and     # update its value     if (L == R):         A[idx] += val         ST[node] += val      else:          # Find the mid         mid = (L + R) // 2          # If node value idx is at the         # left part then update         # the left part         if (L <= idx and idx <= mid):             update(2 * node, L, mid, idx, val)         else:             update(2 * node + 1, mid + 1, R, idx, val)          # Store the information in parents         ST[node] = ST[2 * node] + ST[2 * node + 1]   def query(node, tl, tr, l, r):     global A, ST      # If it lies out of range then     # return 0     if (r < tl or tr < l):         return 0      # If the node contains the range then     # return the node value     if (l <= tl and tr <= r):         return ST[node]     tm = (tl + tr) // 2      # Recursively traverse left and right     # and find the node     return query(2 * node, tl, tm, l, r) + query(2 * node + 1, tm + 1, tr, l, r)   # Driver code if __name__ == "__main__":      n = 6     A = [0, 1, 3, 5, -2, 3]      # Create a segment tree of size 4*n     ST = [0 for _ in range(4 * n)]      # Build a segment tree     build(1, 0, n - 1)     print(f"Sum of values in range 0-4 are: {query(1, 0, n - 1, 0, 4)}")      # Update the value at idx = 1 by     # 100 ths becoming 101     update(1, 0, n - 1, 1, 100)     print("Value at index 1 increased by 100")     print(f"sum of value in range 1-3 are: {query(1, 0, n - 1, 1, 3)}")      # This code is contributed by rakeshsahni 
C#
// C# code for segment tree with sum // range and update query  using System;  public class GFG {      static int n = 6;     static int[] A = { 0, 1, 3, 5, -2, 3 };      // Create a segment tree of size 4*n     static int[] ST = new int[4 * n];      public static void build(int node, int L, int R)     {          // Leaf node where L == R         if (L == R) {             ST[node] = A[L];         }         else {              // Find the middle element to             // split the array into two halves             int mid = (L + R) / 2;              // Recursively travel the             // left half             build(2 * node, L, mid);              // Recursively travel the             // right half             build(2 * node + 1, mid + 1, R);              // Storing the sum of both the             // children into the parent             ST[node] = ST[2 * node] + ST[2 * node + 1];         }     }      public static void update(int node, int L, int R,                               int idx, int val)     {          // Find the lead node and         // update its value         if (L == R) {             A[idx] += val;             ST[node] += val;         }         else {              // Find the mid             int mid = (L + R) / 2;              // If node value idx is at the             // left part then update             // the left part             if (L <= idx && idx <= mid)                 update(2 * node, L, mid, idx, val);             else                 update(2 * node + 1, mid + 1, R, idx, val);              // Store the information in parents             ST[node] = ST[2 * node] + ST[2 * node + 1];         }     }      public static int query(int node, int tl, int tr, int l,                             int r)     {          // If it lies out of range then         // return 0         if (r < tl || tr < l)             return 0;          // If the node contains the range then         // return the node value         if (l <= tl && tr <= r)             return ST[node];         int tm = (tl + tr) / 2;          // Recursively traverse left and right         // and find the node         return query(2 * node, tl, tm, l, r)             + query(2 * node + 1, tm + 1, tr, l, r);     }      static public void Main()     {          // Code         // Build a segment tree         build(1, 0, n - 1);         Console.WriteLine("Sum of values in range 0-4 are: "                           + query(1, 0, n - 1, 0, 4));          // Update the value at idx = 1 by         // 100 ths becoming 101         update(1, 0, n - 1, 1, 100);         Console.WriteLine(             "Value at index 1 increased by 100");         Console.WriteLine("sum of value in range 1-3 are: "                           + query(1, 0, n - 1, 1, 3));     } }  // This code is contributed by lokeshmvs21. 
JavaScript
// JavaScript code for the above approach         function build(node, L, R)         {                      // Leaf node where L == R             if (L === R) {                 ST[node] = A[L];             } else {                 // Find the middle element to split the array into two halves                 const mid = Math.floor((L + R) / 2);                  // Recursively travel the left half                 build(2 * node, L, mid);                  // Recursively travel the right half                 build(2 * node + 1, mid + 1, R);                  // Storing the sum of both the children into the parent                 ST[node] = ST[2 * node] + ST[2 * node + 1];             }         }          function update(node, L, R, idx, val)         {                      // Find the lead node and update its value             if (L === R) {                 A[idx] += val;                 ST[node] += val;             } else {                 // Find the mid                 const mid = Math.floor((L + R) / 2);                  // If node value idx is at the left part then update the left part                 if (L <= idx && idx <= mid) {                     update(2 * node, L, mid, idx, val);                 } else {                     update(2 * node + 1, mid + 1, R, idx, val);                 }                  // Store the information in parents                 ST[node] = ST[2 * node] + ST[2 * node + 1];             }         }          function query(node, tl, tr, l, r) {             // If it lies out of range then return 0             if (r < tl || tr < l) return 0;              // If the node contains the range then return the node value             if (l <= tl && tr <= r) return ST[node];             const tm = Math.floor((tl + tr) / 2);              // Recursively traverse left and right and find the node             return query(2 * node, tl, tm, l, r) + query(2 * node + 1, tm + 1, tr, l, r);         }          // Driver Code         const A = [0, 1, 3, 5, -2, 3];         const ST = new Array(4 * A.length);         // Build a segment tree         build(1, 0, A.length - 1);         console.log(`Sum of values in range 0-4 are: ${query(1, 0, A.length - 1, 0, 4)}<br>`);          // Update the value at idx = 1 by 100 thus becoming 101         update(1, 0, A.length - 1, 1, 100);         console.log(`Value at index 1 increased by 100 <br>`);         console.log(`sum of value in range 1-3 are: ${query(1, 0, A.length - 1, 1, 3)}<br>`);   // This code is contributed by Potta Lokesh 

Output
Sum of values in range 0-4 are: 7 Value at index 1 increased by 100 sum of value in range 1-3 are: 109

Time complexity: O(N)

  • The building operation takes O(N) time
  • The query operation takes O(logN) time
  • Each update is performed in O(logN) time

Auxiliary Space: O(n)

Note:

A segment tree with 2^x leaf nodes will have 2^(x+1)-1 total nodes due to its perfect binary tree structure. However, when dealing with a non-power-of-two number of elements, extra leaf nodes may be present. To represent all elements, the number of leaf nodes must be rounded up to the nearest power of two, resulting in a maximum of almost 2*n leaf nodes.

For instance, if n is 2^j + 1, 2^(j+1) leaf nodes will be required, leading to an O(2*n) space complexity. As the total number of nodes is about twice the number of leaf nodes, the total space complexity of the segment tree is O(4n). The space requirement can be substantial, but it is usually manageable for most practical applications.

Updating an interval (Lazy propagation):

Lazy Propagation: A speedup technique for range updates

Example of segment tree

Example of segment tree

  • We can delay some updates (avoid recursive calls in update) and do such updates only when necessary when there are several updates and updates are being performed on a range.
  • A node in a segment tree stores or displays the results of a query for a variety of indexes. 
  • Additionally, all of the node’s descendants must also be updated if the update operation’s range includes this node. 
    • Take the node with the value 27 in the picture above as an example. This node contains the sum of values at the indexes 3 to 5. This node and all of its descendants must be updated if our update query covers the range of 2 to 5.
    • By storing this update information in distinct nodes referred to as lazy nodes or values, we use lazy propagation to update only the node with value 27 and delay updates to its descendants. 
  • We make an array called lazy[] to stand in for the lazy node. The size of lazy[] is the same as the array used to represent the segment tree in the code following, which is tree[].
  • The goal is to set all of the lazy[elements] to 0. 
    • There are no pending changes on the segment tree node i if lazy[i] has a value of 0. 
    • A non-zero value for lazy[i] indicates that before doing any queries on node i in the segment tree, this sum needs to be added to the node.

Below is the implementation to demonstrate the working of Lazy Propagation.

C++
// Program to show segment tree to // demonstrate lazy propagation #include <bits/stdc++.h> using namespace std; #define MAX 1000  // Ideally, we should not use global // variables and large constant-sized // arrays, we have done it here for // simplicity.  // To store segment tree int tree[MAX] = { 0 };  // To store pending updates int lazy[MAX] = { 0 };  // si -> index of current node in segment tree // ss and se -> Starting and ending // indices of elements for which current // nodes stores sum. // us and ue -> starting and ending indexes // of update query // diff -> which we need to add in the // range us to ue void updateRangeUtil(int si, int ss, int se, int us, int ue,                      int diff) {    // If lazy value is non-zero for     // current node of segment tree, then     // there are some pending updates. So,     // we need to make sure that the     // pending updates are done before     // making new updates. Because this     // value may be used by parent after     // recursive calls (See last line     // of this function)     if (lazy[si] != 0) {          // Make pending updates using         // value stored in lazy nodes         tree[si] += (se - ss + 1) * lazy[si];          // checking if it is not leaf node         // because if it is leaf node then         // we cannot go further         if (ss != se) {              // We can postpone updating             // children we don't need             // their new values now. Since             // we are not yet updating             // children of si, we need to             // set lazy flags for the children             lazy[si * 2 + 1] += lazy[si];             lazy[si * 2 + 2] += lazy[si];         }          // Set the lazy value for current         // node as 0 as it has been updated         lazy[si] = 0;     }      // out of range     if (ss > se || ss > ue || se < us)         return;      // Current segment is fully in range     if (ss >= us && se <= ue) {          // Add the difference to         // current node         tree[si] += (se - ss + 1) * diff;          // Same logic for checking         // leaf node or not         if (ss != se) {              // This is where we store             // values in lazy nodes,             // rather than updating the             // segment tree itself Since             // we don't need these updated             // values now we postpone             // updates by storing values             // in lazy[]             lazy[si * 2 + 1] += diff;             lazy[si * 2 + 2] += diff;         }         return;     }      // If not completely in rang,     // but overlaps, recur for children,     int mid = (ss + se) / 2;     updateRangeUtil(si * 2 + 1, ss, mid, us, ue, diff);     updateRangeUtil(si * 2 + 2, mid + 1, se, us, ue, diff);      // And use the result of children     // calls to update this node     tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]; }  // Function to update a range of values // in segment tree // us and eu -> starting and ending // indices of update query // ue -> ending index of update query // diff -> which we need to add in the // range us to ue void updateRange(int n, int us, int ue, int diff) {     updateRangeUtil(0, 0, n - 1, us, ue, diff); }  // A recursive function to get the sum of // values in given range of the array. // The following are parameters for this function. // si --> Index of current node in the st. // Initially 0 is passed as root is always // at' index 0 // ss & se --> Starting and ending indices // of the segment represented by current // node, i.e., tree[si] // qs & qe --> Starting and ending // indices of query range int getSumUtil(int ss, int se, int qs, int qe, int si) {      // If lazy flag is set for current     // node of segment tree, then there     // are some pending updates. So we     // need to make sure that the pending     // updates are done before     // processing the sub sum query     if (lazy[si] != 0) {          // Make pending updates to this         // node. Note that this node         // represents sum of elements in         // arr[ss..se]  and all these         // elements must be increased by         // lazy[si]         tree[si] += (se - ss + 1) * lazy[si];          // Checking if it is not leaf node         // because if it is leaf node then         // we cannot go further         if (ss != se) {              // Since we are not yet             // updating children os si,             // we need to set lazy values             // for the children             lazy[si * 2 + 1] += lazy[si];             lazy[si * 2 + 2] += lazy[si];         }          // unset the lazy value for current         // node as it has been updated         lazy[si] = 0;     }      // Out of range     if (ss > se || ss > qe || se < qs)         return 0;      // At this point we are sure that     // pending lazy updates are done for     // current node. So we can return     // value      // If this segment lies in range     if (ss >= qs && se <= qe)         return tree[si];      // If a part of this segment overlaps     // with the given range     int mid = (ss + se) / 2;     return getSumUtil(ss, mid, qs, qe, 2 * si + 1)            + getSumUtil(mid + 1, se, qs, qe, 2 * si + 2); }  // Return sum of elements in range from // index qs (query 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) {         cout << "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 st. void constructSTUtil(int arr[], int ss, int se, int si) {      // Out of range as ss can never     // be greater than se     if (ss > se)         return;      // If there is one element in array,     // store it in current node of segment     // tree and return     if (ss == se) {         tree[si] = arr[ss];         return;     }      // 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 = (ss + se) / 2;     constructSTUtil(arr, ss, mid, si * 2 + 1);     constructSTUtil(arr, mid + 1, se, si * 2 + 2);      tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]; }  // Function to construct segment tree // from given array.This function allocates // memory for segment tree and calls // constructSTUtil() to fill the // allocated memory void constructST(int arr[], int n) {      // Fill the allocated memory st     constructSTUtil(arr, 0, n - 1, 0); }  // 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     constructST(arr, n);      // Print sum of values in array     // from index 1 to 3     cout << "Sum of values in given range = " << getSum(n, 1, 3) << endl;      // Add 10 to all nodes at indexes     // from 1 to 5.     updateRange(n, 1, 5, 10);      // Find sum after the value is updated     cout << "Updated sum of values in given range = " << getSum(n, 1, 3) << endl;      return 0; } 
Java
// Java program to show segment tree to // demonstrate lazy propagation import java.util.*;  class GFG {      // Ideally, we should not use global     // variables and large constant-sized     // arrays, we have done it here for     // simplicity.      static final int MAX = 1000;      // To store segment tree     static int[] tree = new int[MAX];      // To store pending updates     static int[] lazy = new int[MAX];      // si -> index of current node in segment tree     // ss and se -> Starting and ending     // indices of elements for which current     // nodes stores sum.     // us and ue -> starting and ending indexes     // of update query     // diff -> which we need to add in the     // range us to ue     static void updateRangeUtil(int si, int ss, int se,                                 int us, int ue, int diff)     {          // If lazy value is non-zero for         // current node of segment tree, then         // there are some pending updates. So,         // we need to make sure that the         // pending updates are done before         // making new updates. Because this         // value may be used by parent after         // recursive calls (See last line         // of this function)         if (lazy[si] != 0) {              // Make pending updates using             // value stored in lazy nodes             tree[si] += (se - ss + 1) * lazy[si];              // checking if it is not leaf node             // because if it is leaf node then             // we cannot go further             if (ss != se) {                  // We can postpone updating                 // children we don't need                 // their new values now. Since                 // we are not yet updating                 // children of si, we need to                 // set lazy flags for the children                 lazy[si * 2 + 1] += lazy[si];                 lazy[si * 2 + 2] += lazy[si];             }              // Set the lazy value for current             // node as 0 as it has been updated             lazy[si] = 0;         }          // out of range         if (ss > se || ss > ue || se < us) {             return;         }          // Current segment is fully in range         if (ss >= us && se <= ue) {              // Add the difference to             // current node             tree[si] += (se - ss + 1) * diff;              // Same logic for checking             // leaf node or not             if (ss != se) {                  // This is where we store                 // values in lazy nodes,                 // rather than updating the                 // segment tree itself Since                 // we don't need these updated                 // values now we postpone                 // updates by storing values                 // in lazy[]                 lazy[si * 2 + 1] += diff;                 lazy[si * 2 + 2] += diff;             }             return;         }          // If not completely in rang,         // but overlaps, recur for children,         int mid = (ss + se) / 2;         updateRangeUtil(si * 2 + 1, ss, mid, us, ue, diff);         updateRangeUtil(si * 2 + 2, mid + 1, se, us, ue,                         diff);          // And use the result of children         // calls to update this node         tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];     }      // Function to update a range of values     // in segment tree     // us and eu -> starting and ending     // indices of update query     // ue -> ending index of update query     // diff -> which we need to add in the     // range us to ue     static void updateRange(int n, int us, int ue, int diff)     {         updateRangeUtil(0, 0, n - 1, us, ue, diff);     }      // A recursive function to get the sum of     // values in given range of the array.     // The following are parameters for this function.     // si --> Index of current node in the st.     // Initially 0 is passed as root is always     // at' index 0     // ss & se --> Starting and ending indices     // of the segment represented by current     // node, i.e., tree[si]     // qs & qe --> Starting and ending     // indices of query range     static int getSumUtil(int ss, int se, int qs, int qe,                           int si)     {          // If lazy flag is set for current         // node of segment tree, then there         // are some pending updates. So we         // need to make sure that the pending         // updates are done before         // processing the sub sum query         if (lazy[si] != 0) {              // Make pending updates to this             // node. Note that this node             // represents sum of elements in             // arr[ss..se]  and all these             // elements must be increased by             // lazy[si]             tree[si] += (se - ss + 1) * lazy[si];              // Checking if it is not leaf node             // because if it is leaf node then             // we cannot go further             if (ss != se) {                  // Since we are not yet                 // updating children os si,                 // we need to set lazy values                 // for the children                 lazy[si * 2 + 1] += lazy[si];                 lazy[si * 2 + 2] += lazy[si];             }              // unset the lazy value for current             // node as it has been updated             lazy[si] = 0;         }          // Out of range         if (ss > se || ss > qe || se < qs) {             return 0;         }          // At this point we are sure that         // pending lazy updates are done for         // current node. So we can return         // value          // If this segment lies in range         if (ss >= qs && se <= qe) {             return tree[si];         }          // If a part of this segment overlaps         // with the given range         int mid = (ss + se) / 2;         return getSumUtil(ss, mid, qs, qe, 2 * si + 1)             + getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);     }      // Return sum of elements in range from     // index qs (query start) to qe (query end).     // It mainly uses getSumUtil()     static 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 st.     static void constructSTUtil(int arr[], int ss, int se,                                 int si)     {          // Out of range as ss can never         // be greater than se         if (ss > se)             return;          // If there is one element in array,         // store it in current node of segment         // tree and return         if (ss == se) {             tree[si] = arr[ss];             return;         }          // 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 = (ss + se) / 2;         constructSTUtil(arr, ss, mid, si * 2 + 1);         constructSTUtil(arr, mid + 1, se, si * 2 + 2);          tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];     }      // Function to construct segment tree     // from given array.This function allocates     // memory for segment tree and calls     // constructSTUtil() to fill the     // allocated memory     static void constructST(int arr[], int n)     {          // Fill the allocated memory st         constructSTUtil(arr, 0, n - 1, 0);     }      // Driver program to test above functions     public static void main(String[] args)     {         int arr[] = { 1, 3, 5, 7, 9, 11 };         int n = arr.length;          // Build segment tree from given array         constructST(arr, n);          // Print sum of values in array         // from index 1 to 3         System.out.println("Sum of values in given range = "                            + getSum(n, 1, 3));          // Add 10 to all nodes at indexes         // from 1 to 5.         updateRange(n, 1, 5, 10);          // Find sum after the value is updated         System.out.println(             "Updated sum of values in given range = "             + getSum(n, 1, 3));     } } // This code is contributed by Prasad Kandekar(prasad264) 
Python
# Program to show segment tree to # demonstrate lazy propagation MAX = 1000  # Ideally, we should not use global # variables and large constant-sized # arrays, we have done it here for # simplicity.  # To store segment tree tree = [0] * MAX  # To store pending updates lazy = [0] * MAX  # si -> index of current node in segment tree # ss and se -> Starting and ending # indices of elements for which current # nodes stores sum. # us and ue -> starting and ending indexes # of update query # diff -> which we need to add in the # range us to ue   def updateRangeUtil(si, ss, se, us, ue, diff):      # If lazy value is non-zero for     # current node of segment tree, then     # there are some pending updates. So,     # we need to make sure that the     # pending updates are done before     # making new updates. Because this     # value may be used by parent after     # recursive calls (See last line     # of this function)     if lazy[si] != 0:          # Make pending updates using         # value stored in lazy nodes         tree[si] += (se - ss + 1) * lazy[si]          # checking if it is not leaf node         # because if it is leaf node then         # we cannot go further         if ss != se:                          # We can postpone updating             # children we don't need             # their new values now. Since             # we are not yet updating             # children of si, we need to             # set lazy flags for the children             lazy[si * 2 + 1] += lazy[si]             lazy[si * 2 + 2] += lazy[si]          # Set the lazy value for current         # node as 0 as it has been updated         lazy[si] = 0      # out of range     if ss > se or ss > ue or se < us:         return      # Current segment is fully in range     if ss >= us and se <= ue:          # Add the difference to         # current node         tree[si] += (se - ss + 1) * diff          # Same logic for checking         # leaf node or not         if ss != se:              # This is where we store             # values in lazy nodes,             # rather than updating the             # segment tree itself Since             # we don't need these updated             # values now we postpone             # updates by storing values             # in lazy[]             lazy[si * 2 + 1] += diff             lazy[si * 2 + 2] += diff         return      # If not completely in rang,     # but overlaps, recur for children,     mid = (ss + se) // 2     updateRangeUtil(si * 2 + 1, ss, mid, us, ue, diff)     updateRangeUtil(si * 2 + 2, mid + 1, se, us, ue, diff)      # And use the result of children     # calls to update this node     tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]  # Function to update a range of values # in segment tree # us and eu -> starting and ending # indices of update query # ue -> ending index of update query # diff -> which we need to add in the # range us to ue   def updateRange(n, us, ue, diff):     updateRangeUtil(0, 0, n - 1, us, ue, diff)  # A recursive function to get the sum of # values in given range of the array. # The following are parameters for this function. # si --> Index of current node in the st. # Initially 0 is passed as root is always # at' index 0 # ss & se --> Starting and ending indices # of the segment represented by current # node, i.e., tree[si] # qs & qe --> Starting and ending # indices of query range   def getSumUtil(ss, se, qs, qe, si):      # If lazy flag is set for current     # node of segment tree, then there     # are some pending updates. So we     # need to make sure that the pending     # updates are done before     # processing the sub sum query     if lazy[si] != 0:          # Make pending updates to this         # node. Note that this node         # represents sum of elements in         # arr[ss..se]  and all these         # elements must be increased by         # lazy[si]         tree[si] += (se - ss + 1) * lazy[si]          # Checking if it is not leaf node         # because if it is leaf node then         # we cannot go further         if ss != se:              # Since we are not yet             # updating children os si,             # we need to set lazy values             # for the children             lazy[si * 2 + 1] += lazy[si]             lazy[si * 2 + 2] += lazy[si]          # unset the lazy value for current         # node as it has been updated         lazy[si] = 0      # Out of range     if ss > se or ss > qe or se < qs:         return 0      # At this point we are sure that     # pending lazy updates are done for     # current node. So we can return     # value      # If this segment lies in range     if ss >= qs and se <= qe:         return tree[si]      # If a part of this segment overlaps     # with the given range     mid = (ss + se) // 2     return (getSumUtil(ss, mid, qs, qe, 2 * si + 1)             + getSumUtil(mid + 1, se, qs, qe, 2 * si + 2))  # Return sum of elements in range from # index qs (query start) to qe (query end). # It mainly uses getSumUtil()   def getSum(n, qs, qe):      # Check for erroneous input values     if qs < 0 or qe > n - 1 or qs > qe:         print("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 st.   def constructSTUtil(arr, ss, se, si):      # Out of range as ss can never     # be greater than se     if ss > se:         return      # If there is one element in array,     # store it in current node of segment     # tree and return     if ss == se:         tree[si] = arr[ss]         return          # If there are more than one elements,     # then recur for left and right     # subtrees and store the sum of     # values in this node     mid = (ss + se) // 2     constructSTUtil(arr, ss, mid, si * 2 + 1)     constructSTUtil(arr, mid + 1, se, si * 2 + 2)     tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]  # 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):     # Fill the allocated memory st     constructSTUtil(arr, 0, n - 1, 0)   # Driver program to test above functions arr = [1, 3, 5, 7, 9, 11] n = len(arr)  # Build segment tree from given array constructST(arr, n)  # Print sum of values in array # from index 1 to 3 print(f"Sum of values in given range = {getSum(n, 1, 3)}")  # Add 10 to all nodes at indexes # from 1 to 5. updateRange(n, 1, 5, 10)  # Find sum after the value is updated print(f"Updated sum of values in given range = {getSum(n, 1, 3)}") 
C#
// Program to show segment tree to // demonstrate lazy propagation using System;  public class GFG {     const int MAX = 1000;      // Ideally, we should not use global     // variables and large constant-sized     // arrays, we have done it here for     // simplicity.      // To store segment tree     static int[] tree = new int[MAX];      // To store pending updates     static int[] lazy = new int[MAX];      // si -> index of current node in segment tree     // ss and se -> Starting and ending     // indices of elements for which current     // nodes stores sum.     // us and ue -> starting and ending indexes     // of update query     // diff -> which we need to add in the     // range us to ue     static void UpdateRangeUtil(int si, int ss, int se,                                 int us, int ue, int diff)     {          // If lazy value is non-zero for         // current node of segment tree, then         // there are some pending updates. So,         // we need to make sure that the         // pending updates are done before         // making new updates. Because this         // value may be used by parent after         // recursive calls (See last line         // of this function)         if (lazy[si] != 0) {              // Make pending updates using             // value stored in lazy nodes             tree[si] += (se - ss + 1) * lazy[si];              // checking if it is not leaf node             // because if it is leaf node then             // we cannot go further             if (ss != se) {                  // We can postpone updating                 // children we don't need                 // their new values now. Since                 // we are not yet updating                 // children of si, we need to                 // set lazy flags for the children                 lazy[si * 2 + 1] += lazy[si];                 lazy[si * 2 + 2] += lazy[si];             }              // Set the lazy value for current             // node as 0 as it has been updated             lazy[si] = 0;         }          // out of range         if (ss > se || ss > ue || se < us)             return;          // Current segment is fully in range         if (ss >= us && se <= ue) {              // Add the difference to             // current node             tree[si] += (se - ss + 1) * diff;              // Same logic for checking             // leaf node or not             if (ss != se) {                  // This is where we store                 // values in lazy nodes,                 // rather than updating the                 // segment tree itself Since                 // we don't need these updated                 // values now we postpone                 // updates by storing values                 // in lazy[]                 lazy[si * 2 + 1] += diff;                 lazy[si * 2 + 2] += diff;             }             return;         }          // If not completely in rang,         // but overlaps, recur for children,         int mid = (ss + se) / 2;         UpdateRangeUtil(si * 2 + 1, ss, mid, us, ue, diff);         UpdateRangeUtil(si * 2 + 2, mid + 1, se, us, ue,                         diff);          // And use the result of children         // calls to update this node         tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];     }      // Function to update a range of values     // in segment tree     // us and eu -> starting and ending     // indices of update query     // ue -> ending index of update query     // diff -> which we need to add in the     // range us to ue     static void UpdateRange(int n, int us, int ue, int diff)     {         UpdateRangeUtil(0, 0, n - 1, us, ue, diff);     }      // A recursive function to get the sum of     // values in given range of the array.     // The following are parameters for this function.     // si --> Index of current node in the st.     // Initially 0 is passed as root is always     // at' index 0     // ss & se --> Starting and ending indices     // of the segment represented by current     // node, i.e., tree[si]     // qs & qe --> Starting and ending     // indices of query range     static int GetSumUtil(int ss, int se, int qs, int qe,                           int si)     {          // If lazy flag is set for current         // node of segment tree, then there         // are some pending updates. So we         // need to make sure that the pending         // updates are done before         // processing the sub sum query         if (lazy[si] != 0) {              // Make pending updates to this             // node. Note that this node             // represents sum of elements in             // arr[ss..se]  and all these             // elements must be increased by             // lazy[si]             tree[si] += (se - ss + 1) * lazy[si];              // Checking if it is not leaf node             // because if it is leaf node then             // we cannot go further             if (ss != se) {                  // Since we are not yet                 // updating children os si,                 // we need to set lazy values                 // for the children                 lazy[si * 2 + 1] += lazy[si];                 lazy[si * 2 + 2] += lazy[si];             }              // unset the lazy value for current             // node as it has been updated             lazy[si] = 0;         }          // Out of range         if (ss > se || ss > qe || se < qs)             return 0;          // At this point we are sure that         // pending lazy updates are done for         // current node. So we can return         // value          // If this segment lies in range         if (ss >= qs && se <= qe)             return tree[si];          // If a part of this segment overlaps         // with the given range         int mid = (ss + se) / 2;         return GetSumUtil(ss, mid, qs, qe, 2 * si + 1)             + GetSumUtil(mid + 1, se, qs, qe, 2 * si + 2);     }      // Return sum of elements in range from     // index qs (query start) to qe (query end).     // It mainly uses getSumUtil()     static 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 st.     static void ConstructSTUtil(int[] arr, int ss, int se,                                 int si)     {          // Out of range as ss can never         // be greater than se         if (ss > se)             return;          // If there is one element in array,         // store it in current node of segment         // tree and return         if (ss == se) {             tree[si] = arr[ss];             return;         }          // 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 = (ss + se) / 2;         ConstructSTUtil(arr, ss, mid, si * 2 + 1);         ConstructSTUtil(arr, mid + 1, se, si * 2 + 2);          tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];     }      // Function to construct segment tree     // from given array.This function allocates     // memory for segment tree and calls     // constructSTUtil() to fill the     // allocated memory     static void ConstructST(int[] arr, int n)     {          // Fill the allocated memory st         ConstructSTUtil(arr, 0, n - 1, 0);     }      // Driver program to test above functions     static public void Main(string[] args)     {         int[] arr = { 1, 3, 5, 7, 9, 11 };         int n = arr.Length;          // Build segment tree from given array         ConstructST(arr, n);          // Print sum of values in array         // from index 1 to 3         Console.WriteLine("Sum of values in given range = "                           + GetSum(n, 1, 3));          // Add 10 to all nodes at indexes         // from 1 to 5.         UpdateRange(n, 1, 5, 10);          // Find sum after the value is updated         Console.WriteLine(             "Updated sum of values in given range = "             + GetSum(n, 1, 3));     } } // This code is contributed by Prasad Kandekar(prasad264) 
JavaScript
//javascript Program to show segment tree to // demonstrate lazy propagation  let MAX = 1000;  // Ideally, we should not use global // variables and large constant-sized // arrays, we have done it here for // simplicity.  // To store segment tree let tree = new Array(MAX).fill(0);  // To store pending updates let lazy = new Array(MAX).fill(0);  // si -> index of current node in segment tree // ss and se -> Starting and ending // indices of elements for which current // nodes stores sum. // us and ue -> starting and ending indexes // of update query // diff -> which we need to add in the // range us to ue function updateRangeUtil( si,ss, se, us, ue, diff) {   // console.log(si,ss,se,us,ue,diff);     // If lazy value is non-zero for     // current node of segment tree, then     // there are some pending updates. So,     // we need to make sure that the     // pending updates are done before     // making new updates. Because this     // value may be used by parent after     // recursive calls (See last line     // of this function)     if (lazy[si] != 0) {          // Make pending updates using         // value stored in lazy nodes         tree[si] += (se - ss + 1) * lazy[si];          // checking if it is not leaf node         // because if it is leaf node then         // we cannot go further         if (ss != se) {              // We can postpone updating             // children we don't need             // their new values now. Since             // we are not yet updating             // children of si, we need to             // set lazy flags for the children             lazy[si * 2 + 1] += lazy[si];             lazy[si * 2 + 2] += lazy[si];         }          // Set the lazy value for current         // node as 0 as it has been updated         lazy[si] = 0;     }      // out of range     if (ss > se || ss > ue || se < us)         return ;      // Current segment is fully in range     if (ss >= us && se <= ue) {          // Add the difference to         // current node         tree[si] += (se - ss + 1) * diff;          // Same logic for checking         // leaf node or not         if (ss != se) {              // This is where we store             // values in lazy nodes,             // rather than updating the             // segment tree itself Since             // we don't need these updated             // values now we postpone             // updates by storing values             // in lazy[]             lazy[si * 2 + 1] += diff;             lazy[si * 2 + 2] += diff;         }         return;     }      // If not completely in rang,     // but overlaps, recur for children,     let mid = (ss + se) / 2;     updateRangeUtil(Math.floor(si * 2 + 1), Math.floor(ss), Math.floor(mid), Math.floor(us), Math.floor(ue), Math.floor(diff));     updateRangeUtil(Math.floor(si * 2 + 2), Math.floor(mid + 1), Math.floor(se), Math.floor(us), Math.floor(ue), Math.floor(diff));      // And use the result of children     // calls to update this node     tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]; }  // Function to update a range of values // in segment tree // us and eu -> starting and ending // indices of update query // ue -> ending index of update query // diff -> which we need to add in the // range us to ue function updateRange(n, us,  ue, diff) {     updateRangeUtil(0, 0, n - 1, us, ue, diff); }  // A recursive function to get the sum of // values in given range of the array. // The following are parameters for this function. // si --> Index of current node in the st. // Initially 0 is passed as root is always // at' index 0 // ss & se --> Starting and ending indices // of the segment represented by current // node, i.e., tree[si] // qs & qe --> Starting and ending // indices of query range function getSumUtil( ss, se, qs, qe, si) {   // console.log(ss,se,qs,qe,si);     // // If lazy flag is set for current     // node of segment tree, then there     // are some pending updates. So we     // need to make sure that the pending     // updates are done before     // processing the sub sum query     if (lazy[si] != 0) {          // Make pending updates to this         // node. Note that this node         // represents sum of elements in         // arr[ss..se]  and all these         // elements must be increased by         // lazy[si]         tree[si] += (se - ss + 1) * lazy[si];          // Checking if it is not leaf node         // because if it is leaf node then         // we cannot go further         if (ss != se) {              // Since we are not yet             // updating children os si,             // we need to set lazy values             // for the children             lazy[si * 2 + 1] += lazy[si];             lazy[si * 2 + 2] += lazy[si];         }          // unset the lazy value for current         // node as it has been updated         lazy[si] = 0;     }      // Out of range     if (ss > se || ss > qe || se < qs)         return 0;      // At this point we are sure that     // pending lazy updates are done for     // current node. So we can return     // value      // If this segment lies in range     if (ss >= qs && se <= qe)         return tree[si];      // If a part of this segment overlaps     // with the given range     let mid = (ss + se) / 2;     return getSumUtil(Math.floor(ss), Math.floor(mid), Math.floor(qs), Math.floor(qe), Math.floor(2 * si + 1))            + getSumUtil(Math.floor(mid + 1), Math.floor(se), Math.floor(qs), Math.floor(qe), Math.floor(2 * si + 2)); }  // Return sum of elements in range from // index qs (query start) to qe (query end). // It mainly uses getSumUtil() function getSum (n,  qs, qe) {        // Check for erroneous input values     if (qs < 0 || qe > n - 1 || qs > qe) {         console.log("Invalid Input");         return -1;     } // console.log(n,qs,qe);     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 st. function constructSTUtil( arr, ss,  se, si) {      // console.log(arr,ss,se,si);     // Out of range as ss can never     // be greater than se     if (ss > se)         return;      // If there is one element in array,     // store it in current node of segment     // tree and return     if (ss == se) {         tree[si] = arr[ss];         return;     }      // If there are more than one elements,     // then recur for left and right     // subtrees and store the sum of     // values in this node     let mid = (ss + se) / 2;     constructSTUtil(arr, Math.floor(ss), Math.floor(mid), Math.floor(si * 2 + 1));     constructSTUtil(arr, Math.floor(mid + 1), Math.floor(se), Math.floor(si * 2 + 2));      tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2]; }  // Function to construct segment tree // from given array.This function allocates // memory for segment tree and calls // constructSTUtil() to fill the // allocated memory function constructST(arr,  n) {      // Fill the allocated memory st     constructSTUtil(arr, 0, n - 1, 0); }      let arr = [ 1, 3, 5, 7, 9, 11 ];     let n = arr.length;      // Build segment tree from given array     constructST(arr, n);      // Print sum of values in array     // from index 1 to 3     console.log(`Sum of values in given range = ${getSum(n, 1, 3)}`);      // Add 10 to all nodes at indexes     // from 1 to 5.     updateRange(n, 1, 5, 10);     console.log(`Updated sum of values in given range = ${ getSum(n, 1, 3)}`);  // This code is contributed by ksam24000. 

Output
Sum of values in given range = 15 Updated sum of values in given range = 45

Time Complexity: O(N)
Auxiliary Space: O(MAX)

Applications:

  • Interval scheduling: Segment trees can be used to efficiently schedule non-overlapping intervals, such as scheduling appointments or allocating resources.
  • Range-based statistics: Segment trees can be used to compute range-based statistics such as variance, standard deviation, and percentiles.
  • Image processing: Segment trees are used in image processing algorithms to divide an image into segments based on color, texture, or other attributes.

Advantages:

  • Efficient querying: Segment trees can be used to efficiently answer queries about the minimum, maximum, sum, or other aggregate value of a range of elements in an array.
  • Efficient updates: Segment trees can be used to efficiently update a range of elements in an array, such as incrementing or decrementing a range of values.
  • Flexibility: Segment trees can be used to solve a wide variety of problems involving range queries and updates.

Disadvantages:

  • Complexity: Segment trees can be complex to implement and maintain, especially for large arrays or high-dimensional data.
  • Time complexity: The time complexity of segment tree operations like build, update, and the query is O(log N) , which is higher than some other data structures like the Fenwick tree.
  • Space complexity: The space complexity of a segment tree is O(4N) which is relatively high.


Next Article
Persistent Segment Tree | Set 1 (Introduction)
author
kartik
Improve
Article Tags :
  • DSA
  • Tree
  • Segment-Tree
  • Tutorials
Practice Tags :
  • Segment-Tree
  • 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