Find Array after Q queries where in each query change a[i] to a[i] | x

Given an array of N elements, initially all a[i] = 0. Q queries need to be performed. Each query contains three integers l, r, and x and you need to change all a[i] to (a[i] | x) for all l ≤ i ≤ r and return the array after executing Q queries.
Examples:
Input: N = 3, Q = 2, U = {{1, 3, 1}, {1, 3, 2}}
Output: a[] = {3, 3, 3}
Explanation: Initially, all elements of the array are 0. After execution of the first query, all elements become 1 and after execution of the second query all elements become 3.Input: N = 3, Q = 2, U = {{1, 2, 1}, {3, 3, 2}}
Output: a[] = {1, 1, 2}
Explanation: {0, 0, 0] => {1, 1, 0} => {1, 1, 2}
Naive Approach:
- Initialize the array a of the size N with all elements set to 0.
- For each query in U:
  – Iterate over the range from the  l to r (inclusive).
  – For each index i, perform the bitwise OR operation between the current value at a[i] and x, and update a[i] with the result. - Return the final array a after executing all queries.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>using namespace std;Â
// Function to perform operations on an array based on given// queriesvector<int> GFG(int N, int Q, vector<vector<int> >& U){Â Â Â Â vector<int> a(N, 0);Â
    // Process each query in U    for (const auto& query : U) {        // Start index of range        int l = query[0];Â
        // End index of range        int r = query[1];Â
        // Value to be ORed        int x = query[2];Â
        // Perform OR operation on elements within the range        // [l, r]        for (int i = l - 1; i < r; ++i) {            a[i] |= x;        }    }Â
    return a;}Â
int main(){    // Number of elements in the array    int N = 3;Â
    // Number of queries    int Q = 2;    vector<vector<int> > U        = { { 1, 2, 1 },            { 3, 3, 2 } }; // Queries: [l, r, x]Â
    // Call the function to perform operations on the array    vector<int> result = GFG(N, Q, U);Â
    // Print the resulting array    for (const auto& num : result) {        cout << num << " ";    }    cout << endl;Â
    return 0;} |
Java
// Java code for the above approach:import java.util.ArrayList;import java.util.List;Â
public class Main {    // Function to perform operations on an array based on given     // queries    public static List<Integer> GFG(int N, int Q, List<List<Integer>> U) {        List<Integer> a = new ArrayList<>(N);        for (int i = 0; i < N; i++) {            a.add(0);        }Â
        // Process each query in U        for (List<Integer> query : U) {            // Start index of range            int l = query.get(0);Â
            // End index of range            int r = query.get(1);Â
            // Value to be ORed            int x = query.get(2);Â
            // Perform OR operation on elements within the range             // [l, r]            for (int i = l - 1; i < r; i++) {                a.set(i, a.get(i) | x);            }        }Â
        return a;    }Â
    public static void main(String[] args) {        // Number of elements in the array        int N = 3;Â
        // Number of queries        int Q = 2;        List<List<Integer>> U = new ArrayList<>();        U.add(List.of(1, 2, 1));        U.add(List.of(3, 3, 2)); // Queries: [l, r, x]Â
        // Call the function to perform operations on the array        List<Integer> result = GFG(N, Q, U);Â
        // Print the resulting array        for (int num : result) {            System.out.print(num + " ");        }        System.out.println();    }}Â
Â
// This code is contributed by Utkarsh Kumar |
C#
using System;using System.Collections.Generic;Â
class Program{    // Function to perform operations on an     // array based on given queries    static List<int> Geek(int N, int Q, List<List<int>> U)    {        List<int> a = new List<int>(new int[N]);        // Process each query in U        foreach (var query in U)        {            // Start index of range            int l = query[0];            // End index of range            int r = query[1];            // Value to be ORed            int x = query[2];            // Perform OR operation on elements within             // the range [l, r]            for (int i = l - 1; i < r; ++i)            {                a[i] |= x;            }        }        return a;    }    static void Main(string[] args)    {        // Number of elements in the array        int N = 3;        // Number of queries        int Q = 2;        List<List<int>> U = new List<List<int>>        {            new List<int> { 1, 2, 1 },            new List<int> { 3, 3, 2 },        }; // Queries: [l, r, x]        List<int> result = Geek(N, Q, U);        // Print the resulting array        foreach (var num in result)        {            Console.Write(num + " ");        }        Console.WriteLine();    }} |
1 1 2
Time complexity: O(N * Q), where N is the number of elements in the array and Q is the number of queries.
Auxiliary space: O(N) because it uses an additional vector a to store the resulting array of size N.
Efficient Approach:
To solve this problem efficiently, we have to use the concept of difference arrays for each bit.
Below are the steps for the above approach:
- Create a 2D difference array say, dp[][] of size N*20. For every index, keep an array of size 20 to store the bits and initialize every index as 0.
- For each query of l, r, and x, increment those indices of the dp[l] array where the bit position of x is set and decrement those indexes of the dp[r+1] array where the bit position of x is set.
- For each bit, we will run a loop from i=1 to N. And add the value of the previous index to the value of the current index, dp[i][j] += dp[i-1][j].
- Declare an array, say a[] which will be the answer array.
- Every inner array of dp[][] array represents a number. That means every index of the inner array represents the bit of a number. So put the numbers in their appropriate positions and return them.
Below is the implementation of the above approach:
C++
// C++ code for the above approach:#include <bits/stdc++.h>using namespace std;Â
vector<int> updateQuery(int N, int Q,                        vector<vector<int> >& U){Â
    // Code here    vector<int> a(N);    fill(a.begin(), a.end(), 0);    int dp[N][20];    for (int i = 0; i < N; i++) {        for (int j = 0; j < 20; j++)            dp[i][j] = 0;    }    for (int j = 0; j < U.size(); j++) {        for (int i = 0; i < 20; i++) {            if (U[j][2] & (1 << i)) {                dp[U[j][0] - 1][i]++;                if (U[j][1] < N)                    dp[U[j][1]][i]--;            }        }    }    for (int j = 0; j < 20; j++) {        for (int i = 1; i < N; i++) {            dp[i][j] += dp[i - 1][j];        }    }    for (int i = 0; i < N; i++) {        int ans = 0;        for (int j = 0; j < 20; j++) {            if (dp[i][j])                ans += (1 << j);        }        a[i] = ans;    }    return a;}Â
// Drivers codeint main(){Â
    int N = 3, Q = 2;    vector<vector<int> > u = { { 1, 2, 1 }, { 3, 3, 2 } };Â
    // Function Call    vector<int> ans = updateQuery(N, Q, u);    for (auto it : ans)        cout << it << " ";    return 0;} |
Java
// Java code for the above approach:Â
import java.util.*;Â
class GFG {Â Â Â Â public static void main(String[] args) {Â Â Â Â Â Â Â Â int N = 3, Q = 2;Â Â Â Â Â Â Â Â List<List<Integer>> U = new ArrayList<>();Â Â Â Â Â Â Â Â U.add(Arrays.asList(1, 2, 1));Â Â Â Â Â Â Â Â U.add(Arrays.asList(3, 3, 2));Â
        List<Integer> ans = updateQuery(N, Q, U);        for (int it : ans)            System.out.print(it + " ");    }Â
    static List<Integer> updateQuery(int N, int Q, List<List<Integer>> U) {        List<Integer> a = new ArrayList<>();        for (int i = 0; i < N; i++)            a.add(0);Â
        int[][] dp = new int[N][20];        for (int i = 0; i < N; i++) {            for (int j = 0; j < 20; j++)                dp[i][j] = 0;        }Â
        for (int j = 0; j < U.size(); j++) {            for (int i = 0; i < 20; i++) {                if ((U.get(j).get(2) & (1 << i)) != 0) {                    dp[U.get(j).get(0) - 1][i]++;                    if (U.get(j).get(1) < N)                        dp[U.get(j).get(1)][i]--;                }            }        }Â
        for (int j = 0; j < 20; j++) {            for (int i = 1; i < N; i++) {                dp[i][j] += dp[i - 1][j];            }        }Â
        for (int i = 0; i < N; i++) {            int ansVal = 0;            for (int j = 0; j < 20; j++) {                if (dp[i][j] != 0)                    ansVal += (1 << j);            }            a.set(i, ansVal);        }        return a;    }} |
Python3
# Python3 code for the above approach:Â
def updateQuery(N, Q, U):  # Code here  a = [0]*N  dp = [[0]*20 for i in range(N)]  for j in range(len(U)):      for i in range(20):          if (U[j][2] & (1 << i)):              dp[U[j][0] - 1][i] += 1              if (U[j][1] < N):                  dp[U[j][1]][i] -= 1Â
  for j in range(20):      for i in range(1, N):          dp[i][j] += dp[i - 1][j]Â
  for i in range(N):      ans = 0      for j in range(20):          if (dp[i][j]):              ans += (1 << j)      a[i] = ansÂ
  return aÂ
# Drivers codeÂ
N = 3Q = 2U = [ [ 1, 2, 1 ], [ 3, 3, 2 ] ]Â
# Function Callans = updateQuery(N, Q, U)for it in ans:Â Â print(it, end=" ") |
C#
// C# code for the above approach:Â
using System;using System.Collections.Generic;Â
class GFG {    static List<int> UpdateQuery(int N, int Q,                                 List<List<int> > U)    {        List<int> a = new List<int>(new int[N]);        int[, ] dp = new int[N, 20];        for (int i = 0; i < N; i++) {            for (int j = 0; j < 20; j++) {                dp[i, j] = 0;            }        }        for (int j = 0; j < U.Count; j++) {            for (int i = 0; i < 20; i++) {                if ((U[j][2] & (1 << i)) != 0) {                    dp[U[j][0] - 1, i]++;                    if (U[j][1] < N) {                        dp[U[j][1], i]--;                    }                }            }        }        for (int j = 0; j < 20; j++) {            for (int i = 1; i < N; i++) {                dp[i, j] += dp[i - 1, j];            }        }        for (int i = 0; i < N; i++) {            int ans = 0;            for (int j = 0; j < 20; j++) {                if (dp[i, j] != 0) {                    ans += (1 << j);                }            }            a[i] = ans;        }        return a;    }Â
    static void Main(string[] args)    {        int N = 3, Q = 2;        List<List<int> > U = new List<List<int> >();        U.Add(new List<int>{ 1, 2, 1 });        U.Add(new List<int>{ 3, 3, 2 });Â
        // Function Call        List<int> ans = UpdateQuery(N, Q, U);        foreach(var item in ans)        {            Console.Write(item + " ");        }    }} |
Javascript
// JavaScript code for the above approach:Â
function updateQuery(N, Q, U) {Â Â let a = new Array(N).fill(0);Â Â let dp = new Array(N);Â Â for (let i = 0; i < N; i++) {Â Â Â Â dp[i] = new Array(20).fill(0);Â Â }Â Â for (let j = 0; j < U.length; j++) {Â Â Â Â for (let i = 0; i < 20; i++) {Â Â Â Â Â Â if (U[j][2] & (1 << i)) {Â Â Â Â Â Â Â Â dp[U[j][0] - 1][i]++;Â Â Â Â Â Â Â Â if (U[j][1] < N) {Â Â Â Â Â Â Â Â Â Â dp[U[j][1]][i]--;Â Â Â Â Â Â Â Â }Â Â Â Â Â Â }Â Â Â Â }Â Â }Â Â for (let j = 0; j < 20; j++) {Â Â Â Â for (let i = 1; i < N; i++) {Â Â Â Â Â Â dp[i][j] += dp[i - 1][j];Â Â Â Â }Â Â }Â Â for (let i = 0; i < N; i++) {Â Â Â Â let ans = 0;Â Â Â Â for (let j = 0; j < 20; j++) {Â Â Â Â Â Â if (dp[i][j]) {Â Â Â Â Â Â Â Â ans += 1 << j;Â Â Â Â Â Â }Â Â Â Â }Â Â Â Â a[i] = ans;Â Â }Â Â return a;}Â
// Example usagelet N = 3;let Q = 2;let U = [[1, 2, 1], [3, 3, 2]];let ans = updateQuery(N, Q, U);console.log(ans.join(" ")); // Outputs: 1 1 2 |
1 1 2
Time Complexity: O(N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



