GeeksforGeeks App
Open App
Browser
Continue

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

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 ``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

 ``

Output

```2
2
3
2```

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

My Personal Notes arrow_drop_up