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

📅  最后修改于: 2021-09-06 06:26:15             🧑  作者: Mango

给定一个由N 个整数组成的数组 arr[]一个由 {l, r}形式的查询组成的数组Q[][] 。对于每个查询{l, r} ,任务是确定必须添加到该范围内每个数组元素的所有值的最小总和,以便该范围内所有数字的按位与超过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]并将 sum 增加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)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live