Open In App

Find the final Array by updating given Ranges

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] consisting of 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++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to process given range xor
// update queries then printing the
// final array
void printFinalArray(int arr[], int N, int Q[][3], int M)
{
    // printing initial array
    cout << "Initial Array: ";
    for (int i = 0; i < N; i++) {
        cout << arr[i] << "  ";
    }
    cout << endl;
 
    // Precomputation array
    // used for range update
    int prefix[N + 1] = { 0 };
 
    // Traverse the given queries
    for (int i = 0; i < M; i++) {
 
        // Stores range L, R and U for
        // each query
        int L = Q[i][0], R = Q[i][1], U = Q[i][2];
 
        for (int i = L; i <= R; i++) {
            // Updating L and R + 1 with U
            prefix[L] = prefix[L] ^ U;
            prefix[R + 1] = prefix[R + 1] ^ U;
        }
    }
 
    // Taking prefix xor
    // so that every U for M queries
    // carries itself forward from L
    // to R and end at R + 1
    for (int i = 1; i < N; i++) {
        prefix[i] = prefix[i] ^ prefix[i - 1];
    }
 
    // finally printing Final array
    cout << "Final Array: ";
    for (int i = 0; i < N; i++) {
 
        // Taking xor with initial array of
        // prefix array so range updates
        // can be made in initial array
        arr[i] = arr[i] ^ prefix[i];
        cout << arr[i] << "  ";
    }
}
 
// Driver Code
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]);
 
    // Function Call
    printFinalArray(arr, N, Q, M);
 
    return 0;
}


Java




// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to process given range xor
    // update queries then printing the
    // final array
    static void printFinalArray(int[] arr, int N, int[][] Q,
                                int M)
    {
        // Printing initial array
        System.out.print("Initial Array: ");
        for (int i = 0; i < N; i++) {
            System.out.print(arr[i] + "  ");
        }
        System.out.println();
 
        // Precomputation array
        // used for range update
        int[] prefix = new int[N + 1];
        Arrays.fill(prefix, 0);
 
        // Traverse the given queries
        for (int i = 0; i < M; i++) {
 
            // Stores range L, R and U for
            // each query
            int L = Q[i][0], R = Q[i][1], U = Q[i][2];
 
            for (int j = L; j <= R; j++) {
                // Updating L and R + 1 with U
                prefix[L] = prefix[L] ^ U;
                prefix[R + 1] = prefix[R + 1] ^ U;
            }
        }
 
        // Taking prefix xor
        // so that every U for M queries
        // carries itself forward from L
        // to R and end at R + 1
        for (int i = 1; i < N; i++) {
            prefix[i] = prefix[i] ^ prefix[i - 1];
        }
 
        // finally printing Final array
        System.out.print("Final Array: ");
        for (int i = 0; i < N; i++) {
 
            // Taking xor with initial array of
            // prefix array so range updates
            // can be made in initial array
            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;
 
        // Function call
        printFinalArray(arr, N, Q, M);
    }
}
 
// This code is contributed by lokesh.


Python3




# Python code to implement the approach
 
# Function to process given range xor
# update queries then printing the
# final array
def printFinalArray(arr,N,Q,M):
    # printing initial array
    print("Initial Array: ")
    for i in range(N):
        print(arr[i],end=" ")
    print()
     
    # Precomputation array
    # used for range update
    prefix=[0]*(N+1)
     
    # Traverse the given queries
    for i in range(M):
        # Stores range L, R and U for
        # each query
        L=Q[i][0]
        R=Q[i][1]
        U=Q[i][2]
         
        for i in range(L,R+1):
            # Updating L and R + 1 with U
            prefix[L]=prefix[L]^U
            prefix[R+1]=prefix[R+1]^U
     
    # Taking prefix xor
    # so that every U for M queries
    # carries itself forward from L
    # to R and end at R + 1
    for i in range(1,N):
        prefix[i]=prefix[i]^prefix[i-1]
     
    # finally printing Final array
    print("Final Array: ")
    for i in range(N):
        # Taking xor with initial array of
        # prefix array so range updates
        # can be made in initial array
        arr[i]=arr[i]^prefix[i]
        print(arr[i],end=" ")
 
# Driver Code
arr=[0, 0, 0, 0, 0, 0, 0]
Q=[[2,4,1],[0,4,2],[1,5,3]]
N=len(arr)
M=len(Q)
 
# Function Call
printFinalArray(arr,N,Q,M)
 
# This code is contributed by Pushpesh Raj.


C#




// C# code to implement the approach
using System;
using System.Collections;
using System.Collections.Generic;
 
public class GFG {
 
  // Function to process given range xor
  // update queries then printing the
  // final array
  static void printFinalArray(int[] arr, int N, int[, ] Q,
                              int M)
  {
    // Printing initial array
    Console.Write("Initial Array: ");
    for (int i = 0; i < N; i++) {
      Console.Write(arr[i] + "  ");
    }
    Console.WriteLine();
 
    // Precomputation array
    // used for range update
    int[] prefix = new int[N + 1];
    Array.Fill(prefix, 0);
 
    // Traverse the given queries
    for (int i = 0; i < M; i++) {
 
      // Stores range L, R and U for
      // each query
      int L = Q[i, 0], R = Q[i, 1], U = Q[i, 2];
 
      for (int j = L; j <= R; j++) {
        // Updating L and R + 1 with U
        prefix[L] = prefix[L] ^ U;
        prefix[R + 1] = prefix[R + 1] ^ U;
      }
    }
 
    // Taking prefix xor
    // so that every U for M queries
    // carries itself forward from L
    // to R and end at R + 1
    for (int i = 1; i < N; i++) {
      prefix[i] = prefix[i] ^ prefix[i - 1];
    }
 
    // finally printing Final array
    Console.Write("Final Array: ");
    for (int i = 0; i < N; i++) {
 
      // Taking xor with initial array of
      // prefix array so range updates
      // can be made in initial array
      arr[i] = arr[i] ^ prefix[i];
      Console.Write(arr[i] + "  ");
    }
  }
 
  static public void Main()
  {
 
    // Code
    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);
 
    // Function call
    printFinalArray(arr, N, Q, M);
  }
}
 
// This code is contributed by lokeshmvs21.


Javascript




// JavaScript code to implement the approach
 
// Function to process given range xor
// update queries then printing the
// final array
const printFinalArray = (arr, N, Q, M) => {
    // printing initial array
    document.write("Initial Array: ");
    for (let i = 0; i < N; i++) {
        console.log(`${arr[i]} `);
    }
    console.log("<br/>");
 
    // Precomputation array
    // used for range update
    let prefix = new Array(N + 1).fill(0);
 
    // Traverse the given queries
    for (let i = 0; i < M; i++) {
 
        // Stores range L, R and U for
        // each query
        let L = Q[i][0], R = Q[i][1], U = Q[i][2];
 
        for (let i = L; i <= R; i++) {
            // Updating L and R + 1 with U
            prefix[L] = prefix[L] ^ U;
            prefix[R + 1] = prefix[R + 1] ^ U;
        }
    }
 
    // Taking prefix xor
    // so that every U for M queries
    // carries itself forward from L
    // to R and end at R + 1
    for (let i = 1; i < N; i++) {
        prefix[i] = prefix[i] ^ prefix[i - 1];
    }
 
    // finally printing Final array
    console.log("Final Array: ");
    for (let i = 0; i < N; i++) {
 
        // Taking xor with initial array of
        // prefix array so range updates
        // can be made in initial array
        arr[i] = arr[i] ^ prefix[i];
        console.log(`${arr[i]} `);
    }
}
 
// Driver Code
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;
 
// Function Call
printFinalArray(arr, N, Q, M);
 
// This code is contributed by rakeshsahni


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
Previous
Next
Share your thoughts in the comments
Similar Reads