Queries to minimize sum added to given ranges in an array to make their Bitwise AND non-zero - GeeksforGeeks

19 Sep, 2021
Given an array arr[] consisting of N integers an array Q[][] consisting of queries of the form {l, r}. For each query {l, r}, the task is to determine the minimum sum of all values that must be added to each array element in that range such that the Bitwise AND of all numbers in that range exceeds 0. Note: Different values can be added to different integers in the given range. 
Examples:
Input: arr[] = {1, 2, 4, 8}, Q[][] = {{1, 4}, {2, 3}, {1, 3}}Output: 3 2 2Explanation: Binary representation of array elements are as follows:1 – 00012 – 00104 – 01008 – 1000For first query {1, 4}, add 1 to all numbers present in the range except the first number. Therefore, Bitwise AND = (1 & 3 & 5 & 9) = 1 and minimum sum of elements added = 3.For second query {2, 3}, add 2 to 3rd element. Therefore, Bitwise AND = (2 & 6) = 2 and minimum sum of elements added = 2.For third query {1, 3}, add 1 to 2nd and 3rd elements. Therefore, Bitwise AND = (1 & 3 & 5) = 1 and minimum sum of elements added = 2.
Input: arr[] = {4, 6, 5, 3}, Q[][] = {{1, 4}}Output: 1Explanation: Optimal way to make the Bitwise AND non-zero is to add 1 to the last element. Therefore, bitwise AND = (4 & 6 & 5 & 4) = 4 and minimum sum of elements added = 1.
Approach: The idea is to first observe that the Bitwise AND of all the integers in the range [l, r] can only be non-zero if a bit at a particular index is set for each integer in that range. Follow the steps below to solve the problem:
Initialize a 2D vector pre where pre[i][j] stores the minimum sum of integers to be added to all integers from index 0 to index i such that, for each of them, their jth bit is set.For each element at index i, check for each of its bit from j = 0 to 31.Initialize a variable sum with 0.If jth bit is set, update pre[i][j] as pre[i][j]=pre[i-1][j] and increment sum by 2j. Otherwise, update pre[i][j] = pre[i-1][j] + 2j – sum where (2j-sum) is the value that must be added to set the jth bit of arr[i].Now, for each query {l, r}, the minimum sum required to set jth bit of all elements in the given range is pre[r][j] – pre[l-1][j].For each query {l, r}, find the answer for each bit from j = 0 to 31 and print the minimum amongst them.
Initialize a 2D vector pre where pre[i][j] stores the minimum sum of integers to be added to all integers from index 0 to index i such that, for each of them, their jth bit is set.
For each element at index i, check for each of its bit from j = 0 to 31.
Initialize a variable sum with 0.
If jth bit is set, update pre[i][j] as pre[i][j]=pre[i-1][j] and increment sum by 2j. Otherwise, update pre[i][j] = pre[i-1][j] + 2j – sum where (2j-sum) is the value that must be added to set the jth bit of arr[i].
Now, for each query {l, r}, the minimum sum required to set jth bit of all elements in the given range is pre[r][j] – pre[l-1][j].
For each query {l, r}, find the answer for each bit from j = 0 to 31 and print the minimum amongst them.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h>using namespace std; // Function to find the min sum required// to set the jth bit of all integervoid processing(vector<int> v,                vector<vector<long long int> >& pre){     // Number of elements    int N = v.size();     // Traverse all elements    for (int i = 0; i < N; i++) {         // Binary representation        bitset<32> b(v[i]);         long long int sum = 0;         // Take previous values        if (i != 0) {             pre[i] = pre[i - 1];        }         // Processing each bit and        // store it in 2d vector        for (int j = 0; j < 32; j++) {             if (b[j] == 1) {                 sum += 1ll << j;            }            else {                 pre[i][j]                    += (1ll << j) - sum;            }        }    }} // Function to print the minimum// sum for each querylong long intprocess_query(vector<vector<int> > Q,              vector<vector<long long int> >& pre){     // Stores the sum for each query    vector<int> ans;     for (int i = 0; i < Q.size(); i++) {         // Update wrt 0-based index        --Q[i][0], --Q[i][1];         // Initizlize answer        long long int min1 = INT_MAX;         // Find minimum sum for each bit        if (Q[i][0] == 0) {             for (int j = 0; j < 32; j++) {                 min1 = min(pre[Q[i][1]][j], min1);            }        }        else {             for (int j = 0; j < 32; j++) {                 min1 = min(pre[Q[i][1]][j]                               - pre[Q[i][0] - 1][j],                           min1);            }        }         // Store the answer for        // each query        ans.push_back(min1);    }     // Print the answer vector    for (int i = 0; i < ans.size(); i++) {        cout << ans[i] << " ";    }} // Driver Codeint main(){     // Given array    vector<int> arr = { 1, 2, 4, 8 };     // Given Queries    vector<vector<int> > Q        = { { 1, 4 }, { 2, 3 }, { 1, 3 } };     // 2d Prefix vector    vector<vector<long long int> > pre(        100001, vector<long long int>(32, 0));     // Preprocessing    processing(arr, pre);     // Function call for queries    process_query(Q, pre);     return 0;}
3 2 2
 
Time Complexity: O(N*32 + sizeof(Q)*32) Auxiliary Space: O(N*32)
surinderdawra388
array-range-queries
Bitwise-AND
CPP-bitset
prefix-sum
Arrays
Bit Magic
Mathematical
prefix-sum
Arrays
Mathematical
Bit Magic
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Next Greater Element
Window Sliding Technique
Count pairs with given sum
Program to find sum of elements in a given array
Reversal algorithm for array rotation
Bitwise Operators in C/C++
Left Shift and Right Shift Operators in C/C++
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
Count set bits in an integer
Cyclic Redundancy Check and Modulo-2 Division