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:
Find the final Array by updating given Ranges
Next article icon

Range Update Queries to XOR with 1 in a Binary Array.

Last Updated : 25 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a binary array arr[] of size N. The task is to answer Q queries which can be of any one type from below: 
Type 1 – 1 l r : Performs bitwise xor operation on all the array elements from l to r with 1. 
Type 2 – 2 l r : Returns the minimum distance between two elements with value 1 in a subarray [l, r]. 
Type 3 – 3 l r : Returns the maximum distance between two elements with value 1 in a subarray [l, r]. 
Type 4 – 4 l r : Returns the minimum distance between two elements with value 0 in a subarray [l, r]. 
Type 5 – 5 l r : Returns the maximum distance between two elements with value 0 in a subarray [l, r].
Examples: 
 

Input : arr[] = {1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0}, q=5 
Output : 2 2 3 2
Explanation :
query 1 : Type 2, l=3, r=7 
Range 3 to 7 contains { 1, 0, 1, 0, 1 }. 
So, the minimum distance between two elements with value 1 is 2.
query 2 : Type 3, l=2, r=5 
Range 2 to 5 contains { 0, 1, 0, 1 }. 
So, the maximum distance between two elements with value 1 is 2.
query 3 : Type 1, l=1, r=4 
After update array becomes {1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0}
query 4 : Type 4, l=3, r=7 
Range 3 to 7 in updated array contains { 0, 1, 1, 0, 1 }. 
So, the minimum distance between two elements with value 0 is 3.
query 5 : Type 5, l=4, r=9 
Range 4 to 9 contains { 1, 1, 0, 1, 0, 1 }. 
So, the maximum distance between two elements with value 0 is 2.

Approach: 
We will create a segment tree and use range updates with lazy propagation to solve this.

  • Each node in the segment tree will have the index of leftmost 1 as well as rightmost 1, leftmost 0 as well as rightmost 0 and integers containing the maximum and minimum distance between any elements with value 1 in a subarray {l, r} as well as the maximum and minimum distance between any elements with value 0 in a subarray {l, r}. 
     
  • Now, in this segment tree we can merge left and right nodes as below:

CPP

// l1 = leftmost index of 1, l0 = leftmost index of 0.
// r1 = rightmost index of 1, r0 = rightmost index of 0.
// max1 = maximum distance between two 1’s.
// max0 = maximum distance between two 0’s.
// min1 = minimum distance between two 1’s.
// min0 = minimum distance between two 0’s.
node Merge(node left, node right)
{
    node cur;
     
    if left.l0 is valid
        cur.l0 = left.l0
    else
        cur.l0 = r.l0
    // We will do this for all values
    // i.e. cur.r0, cur.l1, cur.r1, cur.l0
     
    // To find the min and max difference between two 1's and 0's
    // we will take min/max value of left side, right side and
    // difference between rightmost index of 1/0 in right node
    // and leftmost index of 1/0 in left node respectively.
         
     cur.min0 = minimum of left.min0 and right.min0
  
     if left.r0 is valid and right.l0 is valid
        cur.min0 = minimum of cur.min0 and (right.l0 - left.r0)
    // We will do this for all max/min values
    // i.e. cur.min0, cur.min1, cur.max1, cur.max0
         
    return cur;
}
                      
                       

Java

// l1 = leftmost index of 1, l0 = leftmost index of 0.
// r1 = rightmost index of 1, r0 = rightmost index of 0.
// max1 = maximum distance between two 1’s.
// max0 = maximum distance between two 0’s.
// min1 = minimum distance between two 1’s.
// min0 = minimum distance between two 0’s.
node Merge(node left, node right)
{
    node cur = new node();
     
    if (left.l0 != null)
        cur.l0 = left.l0;
    else
        cur.l0 = r.l0;
    // We will do this for all values
    // i.e. cur.r0, cur.l1, cur.r1, cur.l0
     
    // To find the min and max difference between two 1's and 0's
    // we will take min/max value of left side, right side and
    // difference between rightmost index of 1/0 in right node
    // and leftmost index of 1/0 in left node respectively.
         
     cur.min0 = Math.min(left.min0,right.min0);
  
     if (left.r0 != null and right.l0 != null)
        cur.min0 = Math.min(cur.min0 , (right.l0 - left.r0));
   
    // We will do this for all max/min values
    // i.e. cur.min0, cur.min1, cur.max1, cur.max0
         
    return cur;
}
 
// This code is contributed by aadityaburujwale.
                      
                       

Python3

def Merge(left, right):
    cur = {}
     
    if left['l0']:
        cur['l0'] = left['l0']
    else:
        cur['l0'] = right['l0']
         
    # We will do this for all values
    # i.e. cur.r0, cur.l1, cur.r1, cur.l0
     
    # To find the min and max difference between two 1's and 0's
    # we will take min/max value of left side, right side and
    # difference between rightmost index of 1/0 in right node
    # and leftmost index of 1/0 in left node respectively.
    cur['min0'] = min(left['min0'], right['min0'])
     
    if left['r0'] and right['l0']:
        cur['min0'] = min(cur['min0'], right['l0'] - left['r0'])
         
    # We will do this for all max/min values
    # i.e. cur.min0, cur.min1, cur.max1, cur.max0
    return cur
   
# This code is contributed by akashish__
                      
                       

C#

// l1 = leftmost index of 1, l0 = leftmost index of 0.
// r1 = rightmost index of 1, r0 = rightmost index of 0.
// max1 = maximum distance between two 1’s.
// max0 = maximum distance between two 0’s.
// min1 = minimum distance between two 1’s.
// min0 = minimum distance between two 0’s.
public Node Merge(Node left, Node right)
{
    Node cur = new Node();
 
    if (left.l0 != null)
        cur.l0 = left.l0;
    else
        cur.l0 = right.l0;
   
    // We will do this for all values
    // i.e. cur.r0, cur.l1, cur.r1, cur.l0
 
    // To find the min and max difference between two 1's and 0's
    // we will take min/max value of left side, right side and
    // difference between rightmost index of 1/0 in right node
    // and leftmost index of 1/0 in left node respectively.
    cur.min0 = Math.Min(left.min0, right.min0);
 
    if (left.r0 != null && right.l0 != null)
        cur.min0 = Math.Min(cur.min0, (right.l0 - left.r0));
 
    // We will do this for all max/min values
    // i.e. cur.min0, cur.min1, cur.max1, cur.max0
    return cur;
}
 
// This code is contributed by akashish__
                      
                       

Javascript

// l1 = leftmost index of 1, l0 = leftmost index of 0.
// r1 = rightmost index of 1, r0 = rightmost index of 0.
// max1 = maximum distance between two 1’s.
// max0 = maximum distance between two 0’s.
// min1 = minimum distance between two 1’s.
// min0 = minimum distance between two 0’s.
function Merge(left, right) {
let cur = {};
 
if (left.l0) {
    cur.l0 = left.l0;
} else {
    cur.l0 = right.l0;
}
// We will do this for all values
// i.e. cur.r0, cur.l1, cur.r1, cur.l0
 
// To find the min and max difference between two 1's and 0's
// we will take min/max value of left side, right side and
// difference between rightmost index of 1/0 in right node
// and leftmost index of 1/0 in left node respectively.
     
cur.min0 = Math.min(left.min0, right.min0);
 
if (left.r0 && right.l0) {
    cur.min0 = Math.min(cur.min0, right.l0 - left.r0);
}
// We will do this for all max/min values
// i.e. cur.min0, cur.min1, cur.max1, cur.max0
     
return cur;
}
// contributed by akashish__
                      
                       

The time and space complexity of the above code is O(1).

  • To handle the range update query, we will use lazy propagation. The update query asks us to xor all the elements in the range from l to r with 1, and from observations, we know that :
       0 xor 1 = 1        1 xor 1 = 0
  • Hence, we can observe that after this update all the 0’s will change to 1 and all the 1’s will change to 0. Thus, in our segment tree nodes, all the corresponding values for 0 and 1 will also get swapped i.e.
       l0 and l1 will get swapped        r0 and r1 will get swapped        min0 and min1 will get swapped        max0 and max1 will get swapped
  • Then, finally to find the answer to tasks 2, 3, 4 and 5 we just need to call query function for the given range {l, r} and i order to find the answer to task 1 we need to call the range update function.


Below is the implementation of the above approach:
 

CPP

// C++ program for the given problem
#include <bits/stdc++.h>
using namespace std;
 
int lazy[100001];
 
// Class for each node
// in the segment tree
class node {
public:
    int l1, r1, l0, r0;
    int min0, max0, min1, max1;
 
    node()
    {
        l1 = r1 = l0 = r0 = -1;
 
        max1 = max0 = INT_MIN;
        min1 = min0 = INT_MAX;
    }
 
} seg[100001];
 
// A utility function for
// merging two nodes
node MergeUtil(node l, node r)
{
    node x;
 
    x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
    x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
 
    x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
    x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
 
    x.min0 = min(l.min0, r.min0);
    if (l.r0 != -1 && r.l0 != -1)
        x.min0 = min(x.min0, r.l0 - l.r0);
 
    x.min1 = min(l.min1, r.min1);
    if (l.r1 != -1 && r.l1 != -1)
        x.min1 = min(x.min1, r.l1 - l.r1);
 
    x.max0 = max(l.max0, r.max0);
    if (l.l0 != -1 && r.r0 != -1)
        x.max0 = max(x.max0, r.r0 - l.l0);
 
    x.max1 = max(l.max1, r.max1);
    if (l.l1 != -1 && r.r1 != -1)
        x.max1 = max(x.max1, r.r1 - l.l1);
 
    return x;
}
 
// utility function
// for updating a node
node UpdateUtil(node x)
{
    swap(x.l0, x.l1);
    swap(x.r0, x.r1);
    swap(x.min1, x.min0);
    swap(x.max0, x.max1);
 
    return x;
}
 
// A recursive function that constructs
// Segment Tree for given string
void Build(int qs, int qe, int ind, int arr[])
{
    // If start is equal to end then
    // insert the array element
    if (qs == qe) {
        if (arr[qs] == 1) {
            seg[ind].l1 = seg[ind].r1 = qs;
        }
        else {
            seg[ind].l0 = seg[ind].r0 = qs;
        }
 
        lazy[ind] = 0;
        return;
    }
    int mid = (qs + qe) >> 1;
 
    // Build the segment tree
    // for range qs to mid
    Build(qs, mid, ind << 1, arr);
 
    // Build the segment tree
    // for range mid+1 to qe
    Build(mid + 1, qe, ind << 1 | 1, arr);
 
    // merge the two child nodes
    // to obtain the parent node
    seg[ind] = MergeUtil(
        seg[ind << 1],
        seg[ind << 1 | 1]);
}
 
// Query in a range qs to qe
node Query(int qs, int qe,
           int ns, int ne, int ind)
{
    if (lazy[ind] != 0) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= lazy[ind];
            lazy[ind * 2 + 1] ^= lazy[ind];
        }
        lazy[ind] = 0;
    }
 
    node x;
 
    // If the range lies in this segment
    if (qs <= ns && qe >= ne)
        return seg[ind];
 
    // If the range is out of the bounds
    // of this segment
    if (ne < qs || ns > qe || ns > ne)
        return x;
 
    // Else query for the right and left
    // child node of this subtree
    // and merge them
    int mid = (ns + ne) >> 1;
 
    node l = Query(qs, qe, ns,
                   mid, ind << 1);
    node r = Query(qs, qe,
                   mid + 1, ne,
                   ind << 1 | 1);
 
    x = MergeUtil(l, r);
    return x;
}
 
// range update using lazy propagation
void RangeUpdate(int us, int ue,
                 int ns, int ne, int ind)
{
    if (lazy[ind] != 0) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= lazy[ind];
            lazy[ind * 2 + 1] ^= lazy[ind];
        }
        lazy[ind] = 0;
    }
 
    // If the range is out of the bounds
    // of this segment
    if (ns > ne || ns > ue || ne < us)
        return;
 
    // If the range lies in this segment
    if (ns >= us && ne <= ue) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= 1;
            lazy[ind * 2 + 1] ^= 1;
        }
        return;
    }
 
    // Else query for the right and left
    // child node of this subtree
    // and merge them
    int mid = (ns + ne) >> 1;
    RangeUpdate(us, ue, ns, mid, ind << 1);
    RangeUpdate(us, ue, mid + 1, ne, ind << 1 | 1);
 
    node l = seg[ind << 1], r = seg[ind << 1 | 1];
    seg[ind] = MergeUtil(l, r);
}
 
// Driver code
int main()
{
 
    int arr[] = { 1, 1, 0,
                  1, 0, 1,
                  0, 1, 0,
                  1, 0, 1,
                  1, 0 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Build the segment tree
    Build(0, n - 1, 1, arr);
 
    // Query of Type 2 in the range 3 to 7
    node ans = Query(3, 7, 0, n - 1, 1);
    cout << ans.min1 << "\n";
 
    // Query of Type 3 in the range 2 to 5
    ans = Query(2, 5, 0, n - 1, 1);
    cout << ans.max1 << "\n";
 
    // Query of Type 1 in the range 1 to 4
    RangeUpdate(1, 4, 0, n - 1, 1);
 
    // Query of Type 4 in the range 3 to 7
    ans = Query(3, 7, 0, n - 1, 1);
    cout << ans.min0 << "\n";
 
    // Query of Type 5 in the range 4 to 9
    ans = Query(4, 9, 0, n - 1, 1);
    cout << ans.max0 << "\n";
 
    return 0;
}
                      
                       

Java

// java code addition
import java.io.*;
import java.util.Arrays;
 
class Node {
    int l1, r1, l0, r0;
    int min0, max0, min1, max1;
 
    public Node() {
        l1 = r1 = l0 = r0 = -1;
        max1 = max0 = Integer.MIN_VALUE;
        min1 = min0 = Integer.MAX_VALUE;
    }
}
 
class LazyPropagationSegmentTree {
    static final int MAX = 100001;
    static int[] lazy = new int[MAX];
    static Node[] seg = new Node[MAX];
 
    public static Node MergeUtil(Node l, Node r) {
        Node x = new Node();
 
        x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
        x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
 
        x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
        x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
 
        x.min0 = Math.min(l.min0, r.min0);
        if (l.r0 != -1 && r.l0 != -1)
            x.min0 = Math.min(x.min0, r.l0 - l.r0);
 
        x.min1 = Math.min(l.min1, r.min1);
        if (l.r1 != -1 && r.l1 != -1)
            x.min1 = Math.min(x.min1, r.l1 - l.r1);
 
        x.max0 = Math.max(l.max0, r.max0);
        if (l.l0 != -1 && r.r0 != -1)
            x.max0 = Math.max(x.max0, r.r0 - l.l0);
 
        x.max1 = Math.max(l.max1, r.max1);
        if (l.l1 != -1 && r.r1 != -1)
            x.max1 = Math.max(x.max1, r.r1 - l.l1);
 
        return x;
    }
 
    public static Node UpdateUtil(Node x) {
        int temp;
        temp = x.l0; x.l0 = x.l1; x.l1 = temp;
        temp = x.r0; x.r0 = x.r1; x.r1 = temp;
        temp = x.min0; x.min0 = x.min1; x.min1 = temp;
        temp = x.max0; x.max0 = x.max1; x.max1 = temp;
 
        return x;
    }
 
    public static void Build(int qs, int qe, int ind, int[] arr) {
        if (qs == qe) {
            if (arr[qs] == 1) {
                seg[ind].l1 = seg[ind].r1 = qs;
            } else {
                seg[ind].l0 = seg[ind].r0 = qs;
            }
 
            lazy[ind] = 0;
            return;
        }
        int mid = (qs + qe) >> 1;
 
        Build(qs, mid, ind << 1, arr);
        Build(mid + 1, qe, ind << 1 | 1, arr);
 
        seg[ind] = MergeUtil(seg[ind << 1], seg[ind << 1 | 1]);
    }
 
    public static Node Query(int qs, int qe, int ns, int ne, int ind) {
        if (lazy[ind] != 0) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne){
                lazy[ind * 2] ^= lazy[ind];
                lazy[ind * 2 + 1] ^= lazy[ind];
            }
            lazy[ind] = 0;
        }
 
        Node x = new Node();
 
        // If the range lies in this segment
        if (qs <= ns && qe >= ne)
            return seg[ind];
 
        // If the range is out of the bounds
        // of this segment
        if (ne < qs || ns > qe || ns > ne)
            return x;
 
        // Else query for the right and left
        // child node of this subtree
        // and merge them
        int mid = (ns + ne) >> 1;
 
        Node l = Query(qs, qe, ns,
                       mid, ind << 1);
        Node r = Query(qs, qe,
                       mid + 1, ne,
                       ind << 1 | 1);
 
        x = MergeUtil(l, r);
        return x;
    }
 
    // range update using lazy propagation
    public static void RangeUpdate(int us, int ue,
                     int ns, int ne, int ind)
    {
        if (lazy[ind] != 0) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne) {
                lazy[ind * 2] ^= lazy[ind];
                lazy[ind * 2 + 1] ^= lazy[ind];
            }
            lazy[ind] = 0;
        }
 
        // If the range is out of the bounds
        // of this segment
        if (ns > ne || ns > ue || ne < us)
            return;
 
        // If the range lies in this segment
        if (ns >= us && ne <= ue) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne) {
                lazy[ind * 2] ^= 1;
                lazy[ind * 2 + 1] ^= 1;
            }
            return;
        }
 
        // Else query for the right and left
        // child node of this subtree
        // and merge them
        int mid = (ns + ne) >> 1;
        RangeUpdate(us, ue, ns, mid, ind << 1);
        RangeUpdate(us, ue, mid + 1, ne, ind << 1 | 1);
 
        Node l = seg[ind << 1], r = seg[ind << 1 | 1];
        seg[ind] = MergeUtil(l, r);
    }
 
    // Driver code
    public static void main(String[] args)
    {
         
        // Initialising segment
        for(int i = 0; i < 100001; i++){
            seg[i] = new Node();
        }
         
        int[] arr = { 1, 1, 0,
                      1, 0, 1,
                      0, 1, 0,
                      1, 0, 1,
                      1, 0 };
        int n = arr.length;
 
        // Build the segment tree
        // Console.WriteLine("HI");
        Build(0, n - 1, 1, arr);
        // Console.WriteLine("HI2");
 
        // Query of Type 2 in the range 3 to 7
        Node ans = Query(3, 7, 0, n - 1, 1);
        System.out.println(ans.min1);
 
        // Query of Type 3 in the range 2 to 5
        ans = Query(2, 5, 0, n - 1, 1);
        System.out.println(ans.max1);
 
        // Query of Type 1 in the range 1 to 4
        RangeUpdate(1, 4, 0, n - 1, 1);
 
        // Query of Type 4 in the range 3 to 7
        ans = Query(3, 7, 0, n - 1, 1);
        System.out.println(ans.min0);
 
        // Query of Type 5 in the range 4 to 9
        ans = Query(4, 9, 0, n - 1, 1);
        System.out.println(ans.max0);
    }
     
}
 
// The code is contributed by Nidhi goel.
                      
                       

Python3

# Python program for the given problem
from sys import maxsize
from typing import List
INT_MAX = maxsize
INT_MIN = -maxsize
lazy = [0 for _ in range(100001)]
 
# Class for each node
# in the segment tree
class node:
    def __init__(self) -> None:
        self.l1 = self.r1 = self.l0 = self.r0 = -1
        self.max0 = self.max1 = INT_MIN
        self.min0 = self.min1 = INT_MAX
 
seg = [node() for _ in range(100001)]
 
# A utility function for
# merging two nodes
def MergeUtil(l: node, r: node) -> node:
    x = node()
 
    x.l0 = l.l0 if (l.l0 != -1) else r.l0
    x.r0 = r.r0 if (r.r0 != -1) else l.r0
 
    x.l1 = l.l1 if (l.l1 != -1) else r.l1
    x.r1 = r.r1 if (r.r1 != -1) else l.r1
 
    x.min0 = min(l.min0, r.min0)
    if (l.r0 != -1 and r.l0 != -1):
        x.min0 = min(x.min0, r.l0 - l.r0)
 
    x.min1 = min(l.min1, r.min1)
    if (l.r1 != -1 and r.l1 != -1):
        x.min1 = min(x.min1, r.l1 - l.r1)
 
    x.max0 = max(l.max0, r.max0)
    if (l.l0 != -1 and r.r0 != -1):
        x.max0 = max(x.max0, r.r0 - l.l0)
 
    x.max1 = max(l.max1, r.max1)
    if (l.l1 != -1 and r.r1 != -1):
        x.max1 = max(x.max1, r.r1 - l.l1)
 
    return x
 
# utility function
# for updating a node
def UpdateUtil(x: node) -> node:
    x.l0, x.l1 = x.l1, x.l0
    x.r0, x.r1 = x.r1, x.r0
    x.min1, x.min0 = x.min0, x.min1
    x.max0, x.max1 = x.max1, x.max0
 
    return x
 
# A recursive function that constructs
# Segment Tree for given string
def Build(qs: int, qe: int, ind: int, arr: List[int]) -> None:
 
  # If start is equal to end then
    # insert the array element
    if (qs == qe):
        if (arr[qs] == 1):
            seg[ind].l1 = seg[ind].r1 = qs
        else:
            seg[ind].l0 = seg[ind].r0 = qs
 
        lazy[ind] = 0
        return
 
    mid = (qs + qe) >> 1
 
    # Build the segment tree
    # for range qs to mid
    Build(qs, mid, ind << 1, arr)
 
    # Build the segment tree
    # for range mid+1 to qe
    Build(mid + 1, qe, ind << 1 | 1, arr)
 
    # merge the two child nodes
    # to obtain the parent node
    seg[ind] = MergeUtil(seg[ind << 1], seg[ind << 1 | 1])
 
# Query in a range qs to qe
def Query(qs: int, qe: int, ns: int, ne: int, ind: int) -> node:
    if (lazy[ind] != 0):
        seg[ind] = UpdateUtil(seg[ind])
        if (ns != ne):
            lazy[ind * 2] ^= lazy[ind]
            lazy[ind * 2 + 1] ^= lazy[ind]
        lazy[ind] = 0
    x = node()
 
    # If the range lies in this segment
    if (qs <= ns and qe >= ne):
        return seg[ind]
 
    # If the range is out of the bounds
    # of this segment
    if (ne < qs or ns > qe or ns > ne):
        return x
 
    # Else query for the right and left
    # child node of this subtree
    # and merge them
    mid = (ns + ne) >> 1
    l = Query(qs, qe, ns, mid, ind << 1)
    r = Query(qs, qe, mid + 1, ne, ind << 1 | 1)
    x = MergeUtil(l, r)
    return x
 
# range update using lazy propagation
def RangeUpdate(us: int, ue: int, ns: int, ne: int, ind: int) -> None:
    if (lazy[ind] != 0):
        seg[ind] = UpdateUtil(seg[ind])
        if (ns != ne):
            lazy[ind * 2] ^= lazy[ind]
            lazy[ind * 2 + 1] ^= lazy[ind]
        lazy[ind] = 0
 
    # If the range is out of the bounds
    # of this segment
    if (ns > ne or ns > ue or ne < us):
        return
 
    # If the range lies in this segment
    if (ns >= us and ne <= ue):
        seg[ind] = UpdateUtil(seg[ind])
        if (ns != ne):
            lazy[ind * 2] ^= 1
            lazy[ind * 2 + 1] ^= 1
        return
 
    # Else query for the right and left
    # child node of this subtree
    # and merge them
    mid = (ns + ne) >> 1
    RangeUpdate(us, ue, ns, mid, ind << 1)
    RangeUpdate(us, ue, mid + 1, ne, ind << 1 | 1)
    l = seg[ind << 1]
    r = seg[ind << 1 | 1]
    seg[ind] = MergeUtil(l, r)
 
# Driver code
if __name__ == "__main__":
    arr = [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0]
    n = len(arr)
 
    # Build the segment tree
    Build(0, n - 1, 1, arr)
 
    # Query of Type 2 in the range 3 to 7
    ans = Query(3, 7, 0, n - 1, 1)
    print(ans.min1)
 
    # Query of Type 3 in the range 2 to 5
    ans = Query(2, 5, 0, n - 1, 1)
    print(ans.max1)
 
    # Query of Type 1 in the range 1 to 4
    RangeUpdate(1, 4, 0, n - 1, 1)
 
    # Query of Type 4 in the range 3 to 7
    ans = Query(3, 7, 0, n - 1, 1)
    print(ans.min0)
 
    # Query of Type 5 in the range 4 to 9
    ans = Query(4, 9, 0, n - 1, 1)
    print(ans.max0)
 
# This code is contributed by sanjeev2552
                      
                       

C#

// C# code addition
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
 
// Class for each node in the segment tree
class Node
{
    public int l1, r1, l0, r0;
    public int min0, max0, min1, max1;
 
    public Node()
    {
        l1 = r1 = l0 = r0 = -1;
        max1 = max0 = int.MinValue;
        min1 = min0 = int.MaxValue;
    }
}
 
 
class LazyPropagationSegmentTree
{
    public static  int MAX = 100001;
    public static  int[] lazy = new int[MAX];
     
 
 
    public static  Node[] seg = new Node[MAX];
     
 
    // A utility function for merging two nodes
    public static Node MergeUtil(Node l, Node r)
    {
        Node x = new Node();
 
        x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
        x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
 
        x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
        x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
 
        x.min0 = Math.Min(l.min0, r.min0);
        if (l.r0 != -1 && r.l0 != -1)
            x.min0 = Math.Min(x.min0, r.l0 - l.r0);
 
        x.min1 = Math.Min(l.min1, r.min1);
        if (l.r1 != -1 && r.l1 != -1)
            x.min1 = Math.Min(x.min1, r.l1 - l.r1);
 
        x.max0 = Math.Max(l.max0, r.max0);
        if (l.l0 != -1 && r.r0 != -1)
            x.max0 = Math.Max(x.max0, r.r0 - l.l0);
 
        x.max1 = Math.Max(l.max1, r.max1);
        if (l.l1 != -1 && r.r1 != -1)
            x.max1 = Math.Max(x.max1, r.r1 - l.l1);
 
        return x;
    }
 
    // A utility function for updating a node
    public static Node UpdateUtil(Node x)
    {
        int temp;
        temp = x.l0; x.l0 = x.l1; x.l1 = temp;
        temp = x.r0; x.r0 = x.r1; x.r1 = temp;
        temp = x.min0; x.min0 = x.min1; x.min1 = temp;
        temp = x.max0; x.max0 = x.max1; x.max1 = temp;
 
        return x;
    }
 
    // A recursive function that constructs
    // Segment Tree for given string
    public static void Build(int qs, int qe, int ind, int[] arr)
    {
        // If start is equal to end then
        // insert the array element
        // Console.WriteLine(ind);
        if (qs == qe) {
            if (arr[qs] == 1) {
                seg[ind].l1 = seg[ind].r1 = qs;
            }
            else {
                seg[ind].l0 = seg[ind].r0 = qs;
            }
 
            lazy[ind] = 0;
            return;
        }
        int mid = (qs + qe) >> 1;
 
        // Build the segment tree
        // for range qs to mid
        Build(qs, mid, ind << 1, arr);
 
        // Build the segment tree
        // for range mid+1 to qe
        Build(mid + 1, qe, ind << 1 | 1, arr);
 
        // merge the two child nodes
        // to obtain the parent node
        seg[ind] = MergeUtil(
            seg[ind << 1],
            seg[ind << 1 | 1]);
    }
 
    // Query in a range qs to qe
    public static Node Query(int qs, int qe,
               int ns, int ne, int ind)
    {
        if (lazy[ind] != 0) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne) {
                lazy[ind * 2] ^= lazy[ind];
                lazy[ind * 2 + 1] ^= lazy[ind];
            }
            lazy[ind] = 0;
        }
 
        Node x = new Node();
 
        // If the range lies in this segment
        if (qs <= ns && qe >= ne)
            return seg[ind];
 
        // If the range is out of the bounds
        // of this segment
        if (ne < qs || ns > qe || ns > ne)
            return x;
 
        // Else query for the right and left
        // child node of this subtree
        // and merge them
        int mid = (ns + ne) >> 1;
 
        Node l = Query(qs, qe, ns,
                       mid, ind << 1);
        Node r = Query(qs, qe,
                       mid + 1, ne,
                       ind << 1 | 1);
 
        x = MergeUtil(l, r);
        return x;
    }
 
    // range update using lazy propagation
    public static void RangeUpdate(int us, int ue,
                     int ns, int ne, int ind)
    {
        if (lazy[ind] != 0) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne) {
                lazy[ind * 2] ^= lazy[ind];
                lazy[ind * 2 + 1] ^= lazy[ind];
            }
            lazy[ind] = 0;
        }
 
        // If the range is out of the bounds
        // of this segment
        if (ns > ne || ns > ue || ne < us)
            return;
 
        // If the range lies in this segment
        if (ns >= us && ne <= ue) {
            seg[ind] = UpdateUtil(seg[ind]);
            if (ns != ne) {
                lazy[ind * 2] ^= 1;
                lazy[ind * 2 + 1] ^= 1;
            }
            return;
        }
 
        // Else query for the right and left
        // child node of this subtree
        // and merge them
        int mid = (ns + ne) >> 1;
        RangeUpdate(us, ue, ns, mid, ind << 1);
        RangeUpdate(us, ue, mid + 1, ne, ind << 1 | 1);
 
        Node l = seg[ind << 1], r = seg[ind << 1 | 1];
        seg[ind] = MergeUtil(l, r);
    }
 
    // Driver code
    static void Main()
    {
         
        // Initialising segment
        for(int i = 0; i < 100001; i++){
            seg[i] = new Node();
        }
         
        int[] arr = { 1, 1, 0,
                      1, 0, 1,
                      0, 1, 0,
                      1, 0, 1,
                      1, 0 };
        int n = arr.Length;
 
        // Build the segment tree
        // Console.WriteLine("HI");
        Build(0, n - 1, 1, arr);
        // Console.WriteLine("HI2");
 
        // Query of Type 2 in the range 3 to 7
        Node ans = Query(3, 7, 0, n - 1, 1);
        Console.WriteLine(ans.min1);
 
        // Query of Type 3 in the range 2 to 5
        ans = Query(2, 5, 0, n - 1, 1);
        Console.WriteLine(ans.max1);
 
        // Query of Type 1 in the range 1 to 4
        RangeUpdate(1, 4, 0, n - 1, 1);
 
        // Query of Type 4 in the range 3 to 7
        ans = Query(3, 7, 0, n - 1, 1);
        Console.WriteLine(ans.min0);
 
        // Query of Type 5 in the range 4 to 9
        ans = Query(4, 9, 0, n - 1, 1);
        Console.WriteLine(ans.max0);
    }
     
}
 
// The code is contributed by Nidhi goel.
                      
                       

Javascript

<script>
// javascript program for the given problem
 
 
// Class for each node
// in the segment tree
class node {
     
    constructor()
    {
        this.l1 = this.r1 = this.l0 = this.r0 = -1;
 
        this.max1 = this.max0 = -2000;
        this.min1 = this.min0 = 2000;
    }
 
}
 
let seg = new Array(100001);
for(let i = 0; i < 100001; i++){
    seg[i] = new node();
}
let lazy = new Array(100001);
 
// A utility function for
// merging two nodes
function MergeUtil(l, r)
{
    let x = new node();
 
    x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
    x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
 
    x.l1 = (l.l1 != -1) ? l.l1 : r.l1;
    x.r1 = (r.r1 != -1) ? r.r1 : l.r1;
 
    x.min0 = Math.min(l.min0, r.min0);
    if (l.r0 != -1 && r.l0 != -1)
        x.min0 = Math.min(x.min0, r.l0 - l.r0);
 
    x.min1 = Math.min(l.min1, r.min1);
    if (l.r1 != -1 && r.l1 != -1)
        x.min1 = Math.min(x.min1, r.l1 - l.r1);
 
    x.max0 = Math.max(l.max0, r.max0);
    if (l.l0 != -1 && r.r0 != -1)
        x.max0 = Math.max(x.max0, r.r0 - l.l0);
 
    x.max1 = Math.max(l.max1, r.max1);
    if (l.l1 != -1 && r.r1 != -1)
        x.max1 = Math.max(x.max1, r.r1 - l.l1);
 
    return x;
}
 
// utility function
// for updating a node
function UpdateUtil(x)
{
    // swap l0, and l1
    let temp = x.l0;
    x.l0 = x.l1;
    x.l1 = temp;
     
    // swap l0, and l1
    temp = x.r0;
    x.r0 = x.r1;
    x.r1 = temp;
     
    // swap l0, and l1
    temp = x.min0;
    x.min0 = x.min1;
    x.min1 = temp;
     
    // swap max0, and max1
    temp = x.max0;
    x.max0 = x.max1;
    x.max1 = temp;
 
    return x;
}
 
// A recursive function that constructs
// Segment Tree for given string
function Build(qs, qe, ind, arr)
{
    // If start is equal to end then
    // insert the array element
    if (qs == qe) {
        if (arr[qs] == 1) {
            seg[ind].l1 = seg[ind].r1 = qs;
        }
        else {
            seg[ind].l0 = seg[ind].r0 = qs;
        }
 
        lazy[ind] = 0;
        return;
    }
    let mid = (qs + qe) >> 1;
 
    // Build the segment tree
    // for range qs to mid
    Build(qs, mid, ind << 1, arr);
 
    // Build the segment tree
    // for range mid+1 to qe
    Build(mid + 1, qe, ind << 1 | 1, arr);
 
    // merge the two child nodes
    // to obtain the parent node
    seg[ind] = MergeUtil(seg[ind << 1],seg[ind << 1 | 1]);
}
 
// Query in a range qs to qe
function Query(qs, qe, ns, ne, ind)
{
    if (lazy[ind] != 0) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= lazy[ind];
            lazy[ind * 2 + 1] ^= lazy[ind];
        }
        lazy[ind] = 0;
    }
 
    let x = new node();
 
    // If the range lies in this segment
    if (qs <= ns && qe >= ne)
        return seg[ind];
 
    // If the range is out of the bounds
    // of this segment
    if (ne < qs || ns > qe || ns > ne)
        return x;
 
    // Else query for the right and left
    // child node of this subtree
    // and merge them
    let mid = (ns + ne) >> 1;
 
    let l = Query(qs, qe, ns, mid, ind << 1);
    let r = Query(qs, qe, mid + 1, ne, ind << 1 | 1);
 
    x = MergeUtil(l, r);
    return x;
}
 
// range update using lazy propagation
function RangeUpdate(us, ue, ns, ne, ind)
{
    if (lazy[ind] != 0) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= lazy[ind];
            lazy[ind * 2 + 1] ^= lazy[ind];
        }
        lazy[ind] = 0;
    }
 
    // If the range is out of the bounds
    // of this segment
    if (ns > ne || ns > ue || ne < us)
        return;
 
    // If the range lies in this segment
    if (ns >= us && ne <= ue) {
        seg[ind] = UpdateUtil(seg[ind]);
        if (ns != ne) {
            lazy[ind * 2] ^= 1;
            lazy[ind * 2 + 1] ^= 1;
        }
        return;
    }
 
    // Else query for the right and left
    // child node of this subtree
    // and merge them
    let mid = (ns + ne) >> 1;
    RangeUpdate(us, ue, ns, mid, ind << 1);
    RangeUpdate(us, ue, mid + 1, ne, ind << 1 | 1);
 
    let l = seg[ind << 1], r = seg[ind << 1 | 1];
    seg[ind] = MergeUtil(l, r);
}
 
// Driver code
 
let arr = [1, 1, 0, 1, 0, 1, 0, 1, 0,1, 0, 1,1, 0 ];
let n = arr.length;
 
// Build the segment tree
Build(0, n - 1, 1, arr);
 
// Query of Type 2 in the range 3 to 7
let ans = Query(3, 7, 0, n - 1, 1);
document.write(ans.min1 + 1);
 
// Query of Type 3 in the range 2 to 5
ans = Query(2, 5, 0, n - 1, 1);
document.write(ans.max1);
 
 
// Query of Type 1 in the range 1 to 4
RangeUpdate(1, 4, 0, n - 1, 1);
 
// Query of Type 4 in the range 3 to 7
ans = Query(3, 7, 0, n - 1, 1);
document.write(ans.min0);
 
// Query of Type 5 in the range 4 to 9
ans = Query(4, 9, 0, n - 1, 1);
document.write(ans.max0);
 
// The code is contributed by Nidhi goel.
</script>
                      
                       

Output
2 2 3 2

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



Next Article
Find the final Array by updating given Ranges

M

muskan_garg
Improve
Article Tags :
  • Advanced Data Structure
  • Arrays
  • Competitive Programming
  • Divide and Conquer
  • DSA
  • Tree
  • Write From Home
  • array-range-queries
  • Segment-Tree
Practice Tags :
  • Advanced Data Structure
  • Arrays
  • Divide and Conquer
  • Segment-Tree
  • Tree

Similar Reads

  • Range Queries to Find number of sub-arrays with a given xor
    Given an array arr[] of size n and q queries and an integer k. Each query consists of an index range [l, r] and the task is to count the number of pairs of indices i and j such that l ≤ i ≤ j ≤ r (1-based indexing) and the xor of the elements a[i], a[i + 1], ..., a[j] is equal to k. Example
    5 min read
  • XOR in a range of a binary array
    Given a binary array arr[] of size N and some queries. Each query represents an index range [l, r]. The task is to find the xor of the elements in the given index range for each query i.e. arr[l] ^ arr[l + 1] ^ ... ^ arr[r]. Examples: Input: arr[] = {1, 0, 1, 1, 0, 1, 1}, q[][] = {{0, 3}, {0, 2}} Ou
    7 min read
  • Queries to calculate Bitwise AND of an array with updates
    Given an array arr[] consisting of N positive integers and a 2D array Q[][] consisting of queries of the type {i, val}, the task for each query is to replace arr[i] by val and calculate the Bitwise AND of the modified array. Examples: Input: arr[] = {1, 2, 3, 4, 5}, Q[][] = {{0, 2}, {3, 3}, {4, 2}}O
    15+ min read
  • Queries to calculate Bitwise OR of an array with updates
    Given an array arr[ ] consisting of N positive integers and a 2D array Q[][] consisting of queries of the form {i, val}, the task for each query is to replace arr[i] by val and calculate the Bitwise OR of the modified array. Examples: Input: arr[ ]= {1, 2, 3}, Q[ ][] = {{1, 4}, {3, 0}}Output: 7 6Exp
    10 min read
  • Find the final Array by updating given Ranges
    Given an array arr[] consisting of N integers and an array Q[][3] consisting of M queries of the form [L, R, U], the task for each query is to xor every array element over the range [L, R] with U, After processing each query print the final array. Examples: Input: arr[] = {0, 0, 0, 0, 0, 0, 0}, Q[][
    10 min read
  • Bitwise XOR of a Binary array
    Given a binary array arr[], the task is to calculate the bitwise XOR of all the elements in this array and print it. Examples: Input: arr[] = {“100”, “1001”, “0011”} Output: 1110 0100 XOR 1001 XOR 0011 = 1110 Input: arr[] = {“10”, “11”, “1000001”} Output: 1000000 Approach: Step 1: First find the max
    7 min read
  • Binary array after M range toggle operations
    Consider a binary array consisting of N elements (initially all elements are 0). After that, you are given M commands where each command is of form a b, which means you have to toggle all the elements of the array in range a to b (both inclusive). After the execution of all M commands, you have to f
    6 min read
  • Generate an Array with XOR of even length prefix as 0 or 1
    Given an integer N, the task is to construct an array of N distinct elements (arr[i] ≤ N+1) such that the bitwise XOR of every prefix having an even length is either 0 or 1. Examples: Input: N = 5Output = 2 3 4 5 6Explanation: XOR from arr[1] to arr[2] = XOR(2, 3) = 1XOR from arr[1] to arr[4] = XOR(
    5 min read
  • Check if Binary Array can be made palindrome after K bitwise XOR with 1
    Given a binary array arr[] of size N and an integer K, the task is to check whether the binary array can be turned into a palindrome after K number of operations where in one operation, any random index can be chosen and the value stored in the index will be replaced by its bitwise XOR(^) with1. Exa
    9 min read
  • Count and Toggle Queries on a Binary Array
    Given a size n in which initially all elements are 0. The task is to perform multiple queries of following two types. The queries can appear in any order. 1. toggle(start, end) : Toggle (0 into 1 or 1 into 0) the values from range 'start' to 'end'. 2. count(start, end) : Count the number of 1's with
    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