📌  相关文章
📜  查询以最小化添加到数组中给定范围的总和以使其按位与非零

📅  最后修改于: 2021-05-07 09:43:55             🧑  作者: Mango

给定一个由N个整数组成的数组arr [] ,一个数组Q [] []由形式为{l,r}的查询组成。对于每个查询{l,r} ,任务是确定必须添加到该范围内的每个数组元素的所有值的最小总和,以使该范围内所有数字的按位AND超过0
注意:可以将不同的值添加到给定范围内的不同整数。

例子:

方法:想法是首先观察到[l,r]范围内所有整数的按位与运算,只有为该范围内的每个整数都设置了特定索引处的位时,才可以是非零。
请按照以下步骤解决问题:

  1. 初始化一个2D向量pre,其中pre [i] [j]存储要与从索引0到索引i的所有整数相加的最小整数和,以便为每个整数设置它们的j位。
  2. 对于索引i处的每个元素,请检查其从j = 0到31的每个位。
  3. 0初始化变量sum
  4. 如果设置了第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位的值。 。
  5. 现在,对于每个查询{l,r} ,设置给定范围内的所有元素的j位所需的最小总和为pre [r] [j] – pre [l-1] [j]
  6. 对于每个查询{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)