给定一个由N 个整数组成的数组 arr[]一个由 {l, r}形式的查询组成的数组Q[][] 。对于每个查询{l, r} ,任务是确定必须添加到该范围内每个数组元素的所有值的最小总和,以便该范围内所有数字的按位与超过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]并将 sum 增加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)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live