📌  相关文章
📜  查询以更新方式计算数组的按位与

📅  最后修改于: 2021-05-17 06:38:49             🧑  作者: Mango

给定一个由N个正整数组成的数组arr []和一个由{i,val}类型的查询组成的2D数组Q [] [] ,每个查询的任务是用val替换arr [i]并按位计算和 修改后的数组。

例子:

天真的方法:最简单的方法是解决给定的问题,即为每个查询更新数组元素,然后通过遍历每个查询中的数组来查找所有数组元素的按位与。

时间复杂度: O(N * Q)
辅助空间: O(1)

高效方法:还可以通过使用辅助数组(例如大小为32 * N的bitCount [] [])将设置的位的总和存储在位置i到数组的j索引的位置,来优化上述方法。因此, bitCount [i] [N – 1]表示使用所有数组元素的位置i处的置位总和。请按照以下步骤解决问题:

  • 初始化数组bitCount [32] [N]以存储数组元素的设置位。
  • 使用变量i遍历范围[ 0,31 ]并执行以下步骤:
    • 如果将A [0]的值设置在第i位置,则将bitCount [i] [0]更新为1 。否则,将其更新为0
    • 使用变量j遍历[1,N – 1]范围内的数组A []并执行以下步骤:
      • 如果将A [j]的值设置在i位置,则将bitCount [i] [j]更新为1
      • bitCount [i] [j – 1]的值添加到bitCount [i] [j]中
  • 遍历给定的查询Q [] []数组,然后执行以下步骤:
    • 初始化一个变量,例如res0 ,以存储当前查询的结果。
    • 将当前值存储在currentVal中给定索引处,并将新值存储在newVal中
    • 使用变量i遍历范围[ 0,31 ]
      • 如果在索引i处设置了newVal,而未设置currentVal ,则将prefix [i] [N – 1]递增1
      • 否则,如果在索引i处设置currentVal且未设置newVal ,则将prefix [i] [N – 1]1
      • 如果prefix [i] [N – 1]的值等于N ,请在res中将该位置1。
    • 完成上述步骤后,打印res的值作为结果。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Store the number of set bits at
// each position
int prefixCount[32][10000];
 
// Function to precompute the prefix
// count array
void findPrefixCount(vector arr,
                     int size)
{
    // Iterate over the range[0, 31]
    for (int i = 0; i < 32; i++) {
 
        // Set the bit at position i
        // if arr[0] is set at position i
        prefixCount[i][0]
            = ((arr[0] >> i) & 1);
 
        // Traverse the array and
        // take prefix sum
        for (int j = 1; j < size; j++) {
 
            // Update prefixCount[i][j]
            prefixCount[i][j]
                = ((arr[j] >> i) & 1);
            prefixCount[i][j]
                += prefixCount[i][j - 1];
        }
    }
}
 
// Function to find the Bitwise AND
// of all array elements
void arrayBitwiseAND(int size)
{
    // Stores the required result
    int result = 0;
 
    // Iterate over the range [0, 31]
    for (int i = 0; i < 32; i++) {
 
        // Stores the number of set
        // bits at position i
        int temp = prefixCount[i]
                              [size - 1];
 
        // If temp is N, then set ith
        // position in the result
        if (temp == size)
            result = (result | (1 << i));
    }
 
    // Print the result
    cout << result << " ";
}
 
// Function to update the prefix count
// array in each query
void applyQuery(int currentVal, int newVal,
                int size)
{
    // Iterate through all the bits
    // of the current number
    for (int i = 0; i < 32; i++) {
 
        // Store the bit at position
        // i in the current value and
        // the new value
        int bit1 = ((currentVal >> i) & 1);
        int bit2 = ((newVal >> i) & 1);
 
        // If bit2 is set and bit1 is
        // unset, then increase the
        // set bits at position i by 1
        if (bit2 > 0 && bit1 == 0)
            prefixCount[i][size - 1]++;
 
        // If bit1 is set and bit2 is
        // unset, then decrease the
        // set bits at position i by 1
        else if (bit1 > 0 && bit2 == 0)
            prefixCount[i][size - 1]--;
    }
}
 
// Function to find the bitwise AND
// of the array after each query
void findbitwiseAND(
    vector > queries,
    vector arr, int N, int M)
{
    // Fill the prefix count array
    findPrefixCount(arr, N);
 
    // Traverse the queries
    for (int i = 0; i < M; i++) {
 
        // Store the index and
        // the new value
        int id = queries[i][0];
        int newVal = queries[i][1];
 
        // Store the current element
        // at the index
        int currentVal = arr[id];
 
        // Update the array element
        arr[id] = newVal;
 
        // Apply the changes to the
        // prefix count array
        applyQuery(currentVal, newVal, N);
 
        // Print the bitwise AND of
        // the modified array
        arrayBitwiseAND(N);
    }
}
 
// Driver Code
int main()
{
    vector arr{ 1, 2, 3, 4, 5 };
    vector > queries{ { 0, 2 },
                                  { 3, 3 },
                                  { 4, 2 } };
    int N = arr.size();
    int M = queries.size();
    findbitwiseAND(queries, arr, N, M);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Store the number of set bits at
// each position
static int prefixCount[][];
 
// Function to precompute the prefix
// count array
static void findPrefixCount(int arr[], int size)
{
     
    // Iterate over the range[0, 31]
    for(int i = 0; i < 32; i++)
    {
         
        // Set the bit at position i
        // if arr[0] is set at position i
        prefixCount[i][0] = ((arr[0] >> i) & 1);
 
        // Traverse the array and
        // take prefix sum
        for(int j = 1; j < size; j++)
        {
             
            // Update prefixCount[i][j]
            prefixCount[i][j] = ((arr[j] >> i) & 1);
            prefixCount[i][j] += prefixCount[i][j - 1];
        }
    }
}
 
// Function to find the Bitwise AND
// of all array elements
static void arrayBitwiseAND(int size)
{
     
    // Stores the required result
    int result = 0;
 
    // Iterate over the range [0, 31]
    for(int i = 0; i < 32; i++)
    {
         
        // Stores the number of set
        // bits at position i
        int temp = prefixCount[i][size - 1];
 
        // If temp is N, then set ith
        // position in the result
        if (temp == size)
            result = (result | (1 << i));
    }
 
    // Print the result
    System.out.print(result + " ");
}
 
// Function to update the prefix count
// array in each query
static void applyQuery(int currentVal, int newVal,
                       int size)
{
     
    // Iterate through all the bits
    // of the current number
    for(int i = 0; i < 32; i++)
    {
         
        // Store the bit at position
        // i in the current value and
        // the new value
        int bit1 = ((currentVal >> i) & 1);
        int bit2 = ((newVal >> i) & 1);
 
        // If bit2 is set and bit1 is
        // unset, then increase the
        // set bits at position i by 1
        if (bit2 > 0 && bit1 == 0)
            prefixCount[i][size - 1]++;
 
        // If bit1 is set and bit2 is
        // unset, then decrease the
        // set bits at position i by 1
        else if (bit1 > 0 && bit2 == 0)
            prefixCount[i][size - 1]--;
    }
}
 
// Function to find the bitwise AND
// of the array after each query
static void findbitwiseAND(int queries[][], int arr[],
                           int N, int M)
{
 
    prefixCount = new int[32][10000];
     
    // Fill the prefix count array
    findPrefixCount(arr, N);
 
    // Traverse the queries
    for(int i = 0; i < M; i++)
    {
         
        // Store the index and
        // the new value
        int id = queries[i][0];
        int newVal = queries[i][1];
 
        // Store the current element
        // at the index
        int currentVal = arr[id];
 
        // Update the array element
        arr[id] = newVal;
 
        // Apply the changes to the
        // prefix count array
        applyQuery(currentVal, newVal, N);
 
        // Print the bitwise AND of
        // the modified array
        arrayBitwiseAND(N);
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4, 5 };
    int queries[][] = { { 0, 2 }, { 3, 3 },
                        { 4, 2 } };
    int N = arr.length;
    int M = queries.length;
     
    findbitwiseAND(queries, arr, N, M);
}
}
 
// This code is contributed by Kingash


Python3
# Python3 program for the above approach
 
# Store the number of set bits at
# each position
prefixCount = [[0 for x in range(32)]
                  for y in range(10000)]
 
# Function to precompute the prefix
# count array
def findPrefixCount(arr, size):
     
    # Iterate over the range[0, 31]
    for i in range(32):
 
        # Set the bit at position i
        # if arr[0] is set at position i
        prefixCount[i][0] = ((arr[0] >> i) & 1)
 
        # Traverse the array and
        # take prefix sum
        for j in range(1, size):
 
            # Update prefixCount[i][j]
            prefixCount[i][j] = ((arr[j] >> i) & 1)
            prefixCount[i][j] += prefixCount[i][j - 1]
 
# Function to find the Bitwise AND
# of all array elements
def arrayBitwiseAND(size):
 
    # Stores the required result
    result = 0
 
    # Iterate over the range [0, 31]
    for i in range(32):
 
        # Stores the number of set
        # bits at position i
        temp = prefixCount[i][size - 1]
 
        # If temp is N, then set ith
        # position in the result
        if (temp == size):
            result = (result | (1 << i))
 
    # Print the result
    print(result, end = " ")
 
# Function to update the prefix count
# array in each query
def applyQuery(currentVal, newVal, size):
 
    # Iterate through all the bits
    # of the current number
    for i in range(32):
 
        # Store the bit at position
        # i in the current value and
        # the new value
        bit1 = ((currentVal >> i) & 1)
        bit2 = ((newVal >> i) & 1)
 
        # If bit2 is set and bit1 is
        # unset, then increase the
        # set bits at position i by 1
        if (bit2 > 0 and bit1 == 0):
            prefixCount[i][size - 1] += 1
 
        # If bit1 is set and bit2 is
        # unset, then decrease the
        # set bits at position i by 1
        elif (bit1 > 0 and bit2 == 0):
            prefixCount[i][size - 1] -= 1
 
# Function to find the bitwise AND
# of the array after each query
def findbitwiseAND(queries, arr, N,  M):
 
    # Fill the prefix count array
    findPrefixCount(arr, N)
 
    # Traverse the queries
    for i in range(M):
 
        # Store the index and
        # the new value
        id = queries[i][0]
        newVal = queries[i][1]
 
        # Store the current element
        # at the index
        currentVal = arr[id]
 
        # Update the array element
        arr[id] = newVal
 
        # Apply the changes to the
        # prefix count array
        applyQuery(currentVal, newVal, N)
 
        # Print the bitwise AND of
        # the modified array
        arrayBitwiseAND(N)
 
# Driver Code
if __name__ == "__main__":
 
    arr = [ 1, 2, 3, 4, 5 ]
    queries = [ [ 0, 2 ],
                [ 3, 3 ],
                [ 4, 2 ] ]
    N = len(arr)
    M = len(queries)
     
    findbitwiseAND(queries, arr, N, M)
 
# This code is contributed by ukasp


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Store the number of set bits at
// each position
static int [,]prefixCount = new int[32, 10000];
 
// Function to precompute the prefix
// count array
static void findPrefixCount(List arr,
                            int size)
{
     
    // Iterate over the range[0, 31]
    for(int i = 0; i < 32; i++)
    {
         
        // Set the bit at position i
        // if arr[0] is set at position i
        prefixCount[i, 0] = ((arr[0] >> i) & 1);
 
        // Traverse the array and
        // take prefix sum
        for(int j = 1; j < size; j++)
        {
             
            // Update prefixCount[i][j]
            prefixCount[i, j] = ((arr[j] >> i) & 1);
            prefixCount[i, j] += prefixCount[i, j - 1];
        }
    }
}
 
// Function to find the Bitwise AND
// of all array elements
static void arrayBitwiseAND(int size)
{
     
    // Stores the required result
    int result = 0;
 
    // Iterate over the range [0, 31]
    for(int i = 0; i < 32; i++)
    {
         
        // Stores the number of set
        // bits at position i
        int temp = prefixCount[i, size - 1];
 
        // If temp is N, then set ith
        // position in the result
        if (temp == size)
            result = (result | (1 << i));
    }
     
    // Print the result
    Console.Write(result + " ");
}
 
// Function to update the prefix count
// array in each query
static void applyQuery(int currentVal, int newVal,
                       int size)
{
     
    // Iterate through all the bits
    // of the current number
    for(int i = 0; i < 32; i++)
    {
         
        // Store the bit at position
        // i in the current value and
        // the new value
        int bit1 = ((currentVal >> i) & 1);
        int bit2 = ((newVal >> i) & 1);
 
        // If bit2 is set and bit1 is
        // unset, then increase the
        // set bits at position i by 1
        if (bit2 > 0 && bit1 == 0)
            prefixCount[i, size - 1]++;
 
        // If bit1 is set and bit2 is
        // unset, then decrease the
        // set bits at position i by 1
        else if (bit1 > 0 && bit2 == 0)
            prefixCount[i, size - 1]--;
    }
}
 
// Function to find the bitwise AND
// of the array after each query
static void findbitwiseAND(int [,]queries,
                      List arr, int N, int M)
{
     
    // Fill the prefix count array
    findPrefixCount(arr, N);
 
    // Traverse the queries
    for(int i = 0; i < M; i++)
    {
         
        // Store the index and
        // the new value
        int id = queries[i,0];
        int newVal = queries[i,1];
 
        // Store the current element
        // at the index
        int currentVal = arr[id];
 
        // Update the array element
        arr[id] = newVal;
 
        // Apply the changes to the
        // prefix count array
        applyQuery(currentVal, newVal, N);
 
        // Print the bitwise AND of
        // the modified array
        arrayBitwiseAND(N);
    }
}
 
// Driver Code
public static void Main()
{
    List arr = new List(){ 1, 2, 3, 4, 5 };
    int [,] queries = new int [3, 2]{ { 0, 2 },
                                      { 3, 3 },
                                      { 4, 2 } };
 
    int N = arr.Count;
    int M = 3;
     
    findbitwiseAND(queries, arr, N, M);
}
}
 
// This code is contributed by ipg2016107


输出:
0 0 2

时间复杂度: O(N + M)
辅助空间: O(N)