Find Array after Q queries where in each query change a[i] to a[i] | x
Last Updated :
04 Jan, 2024
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
// queries
vector<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
Python3
# Define a function to perform operations on an array based on given queries
def perform_operations(N, Q, U):
# Initialize an array of size N with zeros
a = [0] * N
# Process each query in U
for query in U:
# Start index of the range
l = query[0]
# End index of the range
r = query[1]
# Value to be ORed
x = query[2]
# Perform OR operation on elements within the range [l, r]
for i in range(l - 1, r):
a[i] |= x
return a
if __name__ == "__main__":
# Number of elements in the array
N = 3
# Number of queries
Q = 2
# Queries: [l, r, x]
U = [
[1, 2, 1],
[3, 3, 2]
]
# Call the function to perform operations on the array
result = perform_operations(N, Q, U)
# Print the resulting array
for num in result:
print(num, end=" ")
print()
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();
}
}
JavaScript
function performOperations(N, Q, U) {
const a = new Array(N).fill(0);
// Process each query in U
for (const query of U) {
// Start index of range
const l = query[0];
// End index of range
const r = query[1];
// Value to be ORed
const x = query[2];
// Perform OR operation on elements within the range [l, r]
for (let i = l - 1; i < r; i++) {
a[i] |= x;
}
}
return a;
}
// Number of elements in the array
const N = 3;
// Number of queries
const Q = 2;
// Queries: [l, r, x]
const U = [
[1, 2, 1],
[3, 3, 2]
];
// Call the function to perform operations on the array
const result = performOperations(N, Q, U);
// Print the resulting array
console.log(result.join(' '));
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 code
int 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 = 3
Q = 2
U = [ [ 1, 2, 1 ], [ 3, 3, 2 ] ]
# Function Call
ans = 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 usage
let 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
Time Complexity: O(N)
Auxiliary Space: O(N)
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem