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

1. 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}.
2. Now, in this segment tree we can merge left and right nodes as below:
 `// 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; ` `} `

3. 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
```
4. 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:

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

Output:
```2
2
3
2
```

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.