给定一个由N个正整数组成的数组arr []和一个由{i,val}类型的查询组成的2D数组Q [] [] ,每个查询的任务是用val替换arr [i]并按位计算和 修改后的数组。
例子:
Input: arr[] = {1, 2, 3, 4, 5}, Q[][] = {{0, 2}, {3, 3}, {4, 2}}
Output: 0 0 2
Explanation:
Query 1: Update A[0] to 2, then the array modifies to {2, 2, 3, 4, 5}. The Bitwise AND of all the elements is 0.
Query 2: Update A[3] to 3, then the array modifies to {2, 2, 3, 3, 5}. The Bitwise AND of all the elements is 0.
Query 3: Update A[4] to 2, then the modified array, A[]={2, 2, 3, 3, 2}. The Bitwise AND of all the elements is 2.
Input: arr[] = {1, 2, 3}, Q[][] = {{1, 5}, {2, 4}}
Output: 1 0
天真的方法:最简单的方法是解决给定的问题,即为每个查询更新数组元素,然后通过遍历每个查询中的数组来查找所有数组元素的按位与。
时间复杂度: 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 [] []数组,然后执行以下步骤:
- 初始化一个变量,例如res为0 ,以存储当前查询的结果。
- 将当前值存储在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
Javascript
0 0 2
时间复杂度: O(N + M)
辅助空间: O(N)