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[][] = {{2, 4, 1}, {0, 4, 2}, {1, 5, 3}}
Output: Initial Array : 0 0 0 0 0 0 0
Final Array : 2 1 0 0 0 3 0
Explanation: Query 1: For query {2, 4, 1} xor every index from 2 to 4 with 1 so it becomes {0, 0, 1, 1, 1, 0, 0}
Query 2: For query {0, 4, 2} xor every index from 0 to 4 with 2 so it becomes {2, 2, 1 ^ 2, 1 ^ 2, 1 ^ 2, 0, 0} which is {2, 2, 3, 3, 3, 0, 0}
Query 3: For query {1, 5, 3} xor every index from 1 to 5 with 3 so it becomes {2, 2 ^ 3, 1 ^ 2 ^ 3, 1 ^ 2 ^ 3, 1 ^ 2 ^ 3, 3, 0} which is {2, 1, 0, 0, 0, 3, 0}
Input: arr[] = {1, 2, 4, 3, 9}, Q[][] = {{0, 3, 15}, {0, 4, 15}}
Output: Initial Array : 1 2 4 3 9
Final Array : 14 13 11 12 6
Naive Approach: The basic way to solve the problem is as follows:
Iterate from L to R and xor U to all elements from arr[L] to arr[R] for each query.
Time Complexity: O(N * M) where M is the number of queries.
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized based on the following idea:
We can utilise prefix xor (similar to prefix sum) efficiently to be able to perform following queries in constant time. Idea is if we take xor of prefix[L] with U and xor of prefix[R + 1] with U again after doing prefix XOR we can observe that L to R gets updated with xor with U. But when we try to take xor at R + 1 XOR that was carrying itself forward from L in prefix xor gets deleted at R + 1 (since x ^ x == 0).
For Example: {0, 0, 0, 0, 0} and L = 1, R = 3 and U = 10
Updating array at L and R + 1 with U: {0, 10, 0, 0, 10}
- STEP 1: {0, 10, 0, 0, 10}
- STEP 2: {0, 10, 10, 0, 10}
- STEP 3: {0, 10, 10, 10, 10}
- STEP 4: {0, 10, 10, 10, 10 ^ 10} that is {0, 10, 10, 10, 0}
This can be observed that 10 was carrying itself forward but at R + 1 it gets deleted and range from L to R gets updated with xor U. This can be used for all queries.
Follow the steps below to solve the problem:
- The pre-computation array prefix[] is defined
- Traversing for each M query and taking xor of prefix[L] with U and prefix[R + 1] with U.
- Taking prefix xor for every U for M queries carries itself forward from L to R and ends at R + 1.
- Taking xor of respective indexes of the initial array with prefix array and then printing it.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void printFinalArray( int arr[], int N, int Q[][3], int M)
{
cout << "Initial Array: " ;
for ( int i = 0; i < N; i++) {
cout << arr[i] << " " ;
}
cout << endl;
int prefix[N + 1] = { 0 };
for ( int i = 0; i < M; i++) {
int L = Q[i][0], R = Q[i][1], U = Q[i][2];
for ( int i = L; i <= R; i++) {
prefix[L] = prefix[L] ^ U;
prefix[R + 1] = prefix[R + 1] ^ U;
}
}
for ( int i = 1; i < N; i++) {
prefix[i] = prefix[i] ^ prefix[i - 1];
}
cout << "Final Array: " ;
for ( int i = 0; i < N; i++) {
arr[i] = arr[i] ^ prefix[i];
cout << arr[i] << " " ;
}
}
int main()
{
int arr[] = { 0, 0, 0, 0, 0, 0, 0 };
int Q[][3] = { { 2, 4, 1 }, { 0, 4, 2 }, { 1, 5, 3 } };
int N = sizeof (arr) / sizeof (arr[0]);
int M = sizeof (Q) / sizeof (Q[0]);
printFinalArray(arr, N, Q, M);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static void printFinalArray( int [] arr, int N, int [][] Q,
int M)
{
System.out.print( "Initial Array: " );
for ( int i = 0 ; i < N; i++) {
System.out.print(arr[i] + " " );
}
System.out.println();
int [] prefix = new int [N + 1 ];
Arrays.fill(prefix, 0 );
for ( int i = 0 ; i < M; i++) {
int L = Q[i][ 0 ], R = Q[i][ 1 ], U = Q[i][ 2 ];
for ( int j = L; j <= R; j++) {
prefix[L] = prefix[L] ^ U;
prefix[R + 1 ] = prefix[R + 1 ] ^ U;
}
}
for ( int i = 1 ; i < N; i++) {
prefix[i] = prefix[i] ^ prefix[i - 1 ];
}
System.out.print( "Final Array: " );
for ( int i = 0 ; i < N; i++) {
arr[i] = arr[i] ^ prefix[i];
System.out.print(arr[i] + " " );
}
}
public static void main(String[] args)
{
int [] arr = { 0 , 0 , 0 , 0 , 0 , 0 , 0 };
int [][] Q
= { { 2 , 4 , 1 }, { 0 , 4 , 2 }, { 1 , 5 , 3 } };
int N = arr.length;
int M = Q.length;
printFinalArray(arr, N, Q, M);
}
}
|
Python3
def printFinalArray(arr,N,Q,M):
print ( "Initial Array: " )
for i in range (N):
print (arr[i],end = " " )
print ()
prefix = [ 0 ] * (N + 1 )
for i in range (M):
L = Q[i][ 0 ]
R = Q[i][ 1 ]
U = Q[i][ 2 ]
for i in range (L,R + 1 ):
prefix[L] = prefix[L]^U
prefix[R + 1 ] = prefix[R + 1 ]^U
for i in range ( 1 ,N):
prefix[i] = prefix[i]^prefix[i - 1 ]
print ( "Final Array: " )
for i in range (N):
arr[i] = arr[i]^prefix[i]
print (arr[i],end = " " )
arr = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
Q = [[ 2 , 4 , 1 ],[ 0 , 4 , 2 ],[ 1 , 5 , 3 ]]
N = len (arr)
M = len (Q)
printFinalArray(arr,N,Q,M)
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
public class GFG {
static void printFinalArray( int [] arr, int N, int [, ] Q,
int M)
{
Console.Write( "Initial Array: " );
for ( int i = 0; i < N; i++) {
Console.Write(arr[i] + " " );
}
Console.WriteLine();
int [] prefix = new int [N + 1];
Array.Fill(prefix, 0);
for ( int i = 0; i < M; i++) {
int L = Q[i, 0], R = Q[i, 1], U = Q[i, 2];
for ( int j = L; j <= R; j++) {
prefix[L] = prefix[L] ^ U;
prefix[R + 1] = prefix[R + 1] ^ U;
}
}
for ( int i = 1; i < N; i++) {
prefix[i] = prefix[i] ^ prefix[i - 1];
}
Console.Write( "Final Array: " );
for ( int i = 0; i < N; i++) {
arr[i] = arr[i] ^ prefix[i];
Console.Write(arr[i] + " " );
}
}
static public void Main()
{
int [] arr = { 0, 0, 0, 0, 0, 0, 0 };
int [, ] Q
= { { 2, 4, 1 }, { 0, 4, 2 }, { 1, 5, 3 } };
int N = arr.Length;
int M = Q.GetLength(0);
printFinalArray(arr, N, Q, M);
}
}
|
Javascript
const printFinalArray = (arr, N, Q, M) => {
document.write( "Initial Array: " );
for (let i = 0; i < N; i++) {
console.log(`${arr[i]} `);
}
console.log( "<br/>" );
let prefix = new Array(N + 1).fill(0);
for (let i = 0; i < M; i++) {
let L = Q[i][0], R = Q[i][1], U = Q[i][2];
for (let i = L; i <= R; i++) {
prefix[L] = prefix[L] ^ U;
prefix[R + 1] = prefix[R + 1] ^ U;
}
}
for (let i = 1; i < N; i++) {
prefix[i] = prefix[i] ^ prefix[i - 1];
}
console.log( "Final Array: " );
for (let i = 0; i < N; i++) {
arr[i] = arr[i] ^ prefix[i];
console.log(`${arr[i]} `);
}
}
let arr = [0, 0, 0, 0, 0, 0, 0];
let Q = [[2, 4, 1], [0, 4, 2], [1, 5, 3]];
let N = arr.length;
let M = Q.length;
printFinalArray(arr, N, Q, M);
|
Output
Initial Array : 0 0 0 0 0 0 0
Final Array : 2 1 0 0 0 3 0
Time Complexity: O(N + M)
Auxiliary Space: O(N)
Last Updated :
05 Dec, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...