Queries for Bitwise OR in the Index Range [L, R] of the Given Array using C++

In this article, we are given an array of integers. We are tasked to find the bitwise OR of all the numbers present in the given range, for example,

Input: arr[] = {1, 3, 1, 2, 3, 4}, q[] = {{0, 1}, {3, 5}}
Output:
3
7
1 OR 3 = 3
2 OR 3 OR 4 = 7
Input: arr[] = {1, 2, 3, 4, 5}, q[] = {{0, 4}, {1, 3}}
Output:
7
7

In the given problem, we will approach it with a brute force approach and then check if it can work for higher constraints or not. If not, then we will optimize our approach to work for higher constraints as well.

Brute Force Approach

In this approach, we are simply going to traverse through each range and calculate the bitwise OR of all the numbers in that range and print our answer.

Example

#include <bits/stdc++.h>
using namespace std;
int main() {
int arr[] = { 7, 5, 3, 5, 2, 3 };
int n = sizeof(arr) / sizeof(int); // size of our array
int queries[][2] = { { 1, 3 }, { 4, 5 } }; // given queries
int q = sizeof(queries) / sizeof(queries[0]); // number of queries
for(int i = 0; i < q; i++) { // traversing through all the queries
long ans = 0;
for(int j = queries[i][0]; j <= queries[i][1]; j++) // traversing through the range
ans |= arr[j]; // calculating the answer
cout << ans << "\n";
}
return 0;
}

Output

7
3

This approach has a time complexity of O(N*Q) where N is the size of our array and Q is the number of queries now as you can see, this complexity will not work for higher constraints, so now we will optimize our approach such that it works for higher constraints as well.

Efficient Approach

In this approach, we will calculate the prefix bits count, and then we will check whether either of the numbers has a particular bit set. If yes, then we put this bit in the answer; else, we leave this bit.

Example

#include <bits/stdc++.h>

using namespace std;
#define bitt 32
#define MAX (int)10e5

int prefixbits[bitt][MAX];
void bitcount(int *arr, int n) { // making prefix counts
for (int j = 31; j >= 0; j--) {
prefixbits[j][0] = ((arr[0] >> j) & 1);
for (int i = 1; i < n; i++) {
prefixbits[j][i] = arr[i] & (1LL << j);
prefixbits[j][i] += prefixbits[j][i - 1];
}
}
return;
}
int check(int l, int r) { // calculating the answer
long ans = 0; // to avoid overflow we are taking ans as long
for (int i = 0; i < 32; i++) {
int x;
if (l == 0)
x = prefixbits[i][r];
else
x = prefixbits[i][r] - prefixbits[i][l - 1];
if (x != 0)
ans = (ans | (1LL << i));
}
return ans;
}
int main() {
int arr[] = {7, 5, 3, 5, 2, 3};
int n = sizeof(arr) / sizeof(int); // size of our array
bitcount(arr, n);
int queries[][2] = {{1, 3}, {4, 5}}; // given queries
int q = sizeof(queries) / sizeof(queries[0]); // number of queries
for (int i = 0; i < q; i++) {
cout << check(queries[i][0], queries[i][1]) << "\n";
}
return 0;
}

Output

7
3

This approach has a time complexity of O(N), where N is the size of our array so that this approach can work for higher constraints.

Explanation of the above code

In this approach, we are calculating the prefix bits count and storing it. Now we calculate a query we go through that prefix count and remove the bit counts of l-1 such that we have counts of bits of numbers in the range [l, r] now as we know them if a bit is set in any number so if you take it’s bitwise OR with any other number the bit will remain set so using this property of bitwise OR we check if the bit count is not zero that means a number with  set bit is present in the range, so we set that bit of answer and continue through the loop and finally print the answer.

Conclusion

This article solves a problem to calculate Queries for bitwise OR in the index range [L, R] of the given array. We also learned the C++ program for this problem and the complete approach ( Normal and efficient ) by which we solved this problem. We can write the same program in other languages such as C, java, python, and other languages. We hope you find this article helpful.