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

• Last Updated : 10 Jan, 2022

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

• 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;` `// 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;` `// 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);` `    ``// 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;``}`

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

Output:

```2
2
3
2```

My Personal Notes arrow_drop_up