Queries for bitwise AND in the index range [L, R] of the given Array using C++


In this article, we have given a problem in which we are given an array of integers, and we are tasked to find the bitwise AND of the given ranges, for example 7minus;

Input: arr[ ] = {1, 3, 1, 2, 32, 3, 3, 4, 4}, q[ ] = {{0, 1}, {3, 5}}
Output:
1
0 0
1 AND 31 = 1
23 AND 34 AND 4 = 00
Input: arr[ ] = {1, 2, 3, 4, 510, 10 , 12, 16, 8}, q[ ] = {{0, 42}, {1, 33, 4}}
Output:
0 8
0

We are going to apply the brute force approach first and check its time complexity. If our time complexity is not good enough, we will try to develop a better approach.

Brute Force Approach

In the given approach, we will traverse through the given range and find our answer and print it.

Example

#include <bits/stdc++.h>
using namespace std;
int main() {
   int ARR[] = { 10, 10 , 12, 16, 8 };
   int n = sizeof(ARR) / sizeof(int); // size of our array
   int queries[][2] = { {0, 2}, {3, 4} }; // 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 = 1LL << 32;
      ans -= 1; // making all the bits of ans 1
      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

8
0

In this approach, we run a loop through the ranges of each query and print their collective bitwise, AND so the overall complexity of our program becomes O(N*Q), where N is the size of our array and Q is the number of our queries now as you can see this complexity is not suitable for higher constraints so we will be coming up with a faster approach for this problem.

Efficient Approach

In this problem, we precalculate the prefix bit count of the array to calculate the bitwise AND of the given range by checking the contribution of set bits in the given range.

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 == r - l + 1)
         ans = ans | 1LL << i;
      }
   return ans;
}
int main() {
   int ARR[] = { 10, 10 , 12, 16, 8 };
   int n = sizeof(ARR) / sizeof(int); // size of our array
   memset(prefixbits, 0, sizeof(prefixbits)); // initializing all the elements with 0
   bitcount(ARR, n);
   int queries[][2] = {{0, 2}, {3, 4}}; // 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

2
0

In this approach, we are taking a constant time for calculating the queries that substantially decrease our time complexity from O(N*Q) to O(N), where N is the size of our given array now. This program can work for higher constraints as well.

Explanation of the above code

n this approach, we are calculating all the prefix bits count and storing it in the index. Now when we calculate the queries, we just need to check whether a bit has the same count as the number of elements present in the range or not. If yes, we set this bit to 1 in our x, and if no, we leave the bit as if any number present in the given range has that bit 0, so the whole bitwise AND of that bit will be zero, and that’s how we are calculating the bitwise AND.

Conclusion

In this article, we solve a problem to enumerate all the queries for bitwise AND 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.

Updated on: 26-Nov-2021

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements