给定一个由N个整数组成的数组arr [] ,一个数组Q [] []由形式为{l,r}的查询组成。对于每个查询{l,r} ,任务是确定必须添加到该范围内的每个数组元素的所有值的最小总和,以使该范围内所有数字的按位AND超过0 。
注意:可以将不同的值添加到给定范围内的不同整数。
例子:
Input: arr[] = {1, 2, 4, 8}, Q[][] = {{1, 4}, {2, 3}, {1, 3}}
Output: 3 2 2
Explanation: Binary representation of array elements are as follows:
1 – 0001
2 – 0010
4 – 0100
8 – 1000
For 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: 1
Explanation: Optimal way to mmake 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.
方法:想法是首先观察到[l,r]范围内所有整数的按位与运算,只有为该范围内的每个整数都设置了特定索引处的位时,才可以是非零。
请按照以下步骤解决问题:
- 初始化一个2D向量pre,其中pre [i] [j]存储要与从索引0到索引i的所有整数相加的最小整数和,以便为每个整数设置它们的第j位。
- 对于索引i处的每个元素,请检查其从j = 0到31的每个位。
- 用0初始化变量sum 。
- 如果设置了第j个位,则将pre [i] [j]更新为pre [i] [j] = pre [i-1] [j],并将总和增加2 j 。否则,更新pre [i] [j] = pre [i-1] [j] + 2 j – sum ,其中(2 j -sum)是必须设置arr [i]的第j位的值。 。
- 现在,对于每个查询{l,r} ,设置给定范围内的所有元素的第j位所需的最小总和为pre [r] [j] – pre [l-1] [j] 。
- 对于每个查询{l,r} ,找到从j = 0到31的每一位的答案,并在其中列出最小值。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the min sum required
// to set the jth bit of all integer
void processing(vector v,
vector >& 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 query
long long int
process_query(vector > Q,
vector >& pre)
{
// Stores the sum for each query
vector 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 Code
int main()
{
// Given array
vector arr = { 1, 2, 4, 8 };
// Given Queries
vector > Q
= { { 1, 4 }, { 2, 3 }, { 1, 3 } };
// 2d Prefix vector
vector > pre(
100001, vector(32, 0));
// Preprocessing
processing(arr, pre);
// Function call for queries
process_query(Q, pre);
return 0;
}
3 2 2
时间复杂度: O(N * 32 + sizeof(Q)* 32)
辅助空间: O(N * 32)