给定一个由非负整数组成的数组A []和由以下两种类型的查询组成的矩阵Q [] [] :
- (1,l,val):将A [l]更新为A [l] + val 。
- (2,K):查找K的LOWER_BOUND A []的前缀求和阵列英寸如果lower_bound不存在,请打印-1。
第二种类型的每个查询的任务是打印值K的lower_bound的索引。
例子:
Input: A[ ] = {1, 2, 3, 5, 8}, Q[ ][ ] = {{1, 0, 2}, {2, 5}, {1, 3, 5}}
Output: 1
Explanation:
Query 1: Update A[0] to A[0] + 2. Now A[ ] = {3, 2, 3, 5, 8}
Query 2: lower_bound of K = 5 in the prefix sum array {3, 5, 8, 13, 21} is 5 and index = 1.
Query 3: Update A[3] to A[3] + 5. Now A[ ] = {3, 2, 3, 10, 8}
Input: A[ ] = {4, 1, 12, 8, 20}, Q[ ] = {{2, 50}, {1, 3, 12}, {2, 50}}
Output: -1
天真的方法:
最简单的方法是首先构建给定数组A []的前缀和数组,对于类型1的查询,更新值并重新计算前缀和。对于类型2的查询,请对前缀和数组执行二进制搜索以找到下限。
时间复杂度: O(Q *(N * logn))
辅助空间: O(N)
高效方法:
可以使用Fenwick树优化上述方法。使用此数据结构,可以在对数时间内执行前缀和数组中的更新查询。
请按照以下步骤解决问题:
- 使用Fenwick树构造前缀和数组。
- 对于类型1的查询,当l> 0时,通过在l中添加最低有效位,将val添加到遍历到父节点的A [l] 。
- 对于类型2的查询,请在Fenwick树上执行二进制搜索以获取下限。
- 每当出现大于K的前缀总和时,请存储该索引并遍历Fenwick树的左侧。否则,现在遍历Fenwick树的右侧,执行Binary Search 。
- 最后,打印所需的索引。
下面是上述方法的实现:
C++
// C++ program to implement
// the above appraoch
#include
using namespace std;
// Function to calculate and return
// the sum of arr[0..index]
int getSum(int BITree[], int index)
{
int ans = 0;
index += 1;
// Traverse ancestors
// of BITree[index]
while (index > 0)
{
// Update the sum of current
// element of BIT to ans
ans += BITree[index];
// Update index to that
// of the parent node in
// getSum() view by
// subtracting LSB(Least
// Significant Bit)
index -= index & (-index);
}
return ans;
}
// Function to update the Binary Index
// Tree by replacing all ancestores of
// index by their respective sum with val
static void updateBIT(int BITree[], int n,
int index, int val)
{
index = index + 1;
// Traverse all ancestors
// and sum with 'val'.
while (index <= n)
{
// Add 'val' to current
// node of BIT
BITree[index] += val;
// Update index to that
// of the parent node in
// updateBit() view by
// adding LSB(Least
// Significant Bit)
index += index & (-index);
}
}
// Function to construct the Binary
// Indexed Tree for the given array
int* constructBITree(int arr[], int n)
{
// Initialize the
// Binary Indexed Tree
int* BITree = new int[n + 1];
for(int i = 0; i <= n; i++)
BITree[i] = 0;
// Store the actual values in
// BITree[] using update()
for(int i = 0; i < n; i++)
updateBIT(BITree, n, i, arr[i]);
return BITree;
}
// Function to obtian and return
// the index of lower_bound of k
int getLowerBound(int BITree[], int arr[],
int n, int k)
{
int lb = -1;
int l = 0, r = n - 1;
while (l <= r)
{
int mid = l + (r - l) / 2;
if (getSum(BITree, mid) >= k)
{
r = mid - 1;
lb = mid;
}
else
l = mid + 1;
}
return lb;
}
void performQueries(int A[], int n, int q[][3])
{
// Store the Binary Indexed Tree
int* BITree = constructBITree(A, n);
// Solve each query in Q
for(int i = 0;
i < sizeof(q[0]) / sizeof(int);
i++)
{
int id = q[i][0];
if (id == 1)
{
int idx = q[i][1];
int val = q[i][2];
A[idx] += val;
// Update the values of all
// ancestors of idx
updateBIT(BITree, n, idx, val);
}
else
{
int k = q[i][1];
int lb = getLowerBound(BITree,
A, n, k);
cout << lb << endl;
}
}
}
// Driver Code
int main()
{
int A[] = { 1, 2, 3, 5, 8 };
int n = sizeof(A) / sizeof(int);
int q[][3] = { { 1, 0, 2 },
{ 2, 5, 0 },
{ 1, 3, 5 } };
performQueries(A, n, q);
}
// This code is contributed by jrishabh99
Java
// Java program to implement
// the above appraoch
import java.util.*;
import java.io.*;
class GFG {
// Function to calculate and return
// the sum of arr[0..index]
static int getSum(int BITree[],
int index)
{
int ans = 0;
index += 1;
// Traverse ancestors
// of BITree[index]
while (index > 0) {
// Update the sum of current
// element of BIT to ans
ans += BITree[index];
// Update index to that
// of the parent node in
// getSum() view by
// subtracting LSB(Least
// Significant Bit)
index -= index & (-index);
}
return ans;
}
// Function to update the Binary Index
// Tree by replacing all ancestores of
// index by their respective sum with val
static void updateBIT(int BITree[],
int n, int index, int val)
{
index = index + 1;
// Traverse all ancestors
// and sum with 'val'.
while (index <= n) {
// Add 'val' to current
// node of BIT
BITree[index] += val;
// Update index to that
// of the parent node in
// updateBit() view by
// adding LSB(Least
// Significant Bit)
index += index & (-index);
}
}
// Function to construct the Binary
// Indexed Tree for the given array
static int[] constructBITree(
int arr[], int n)
{
// Initialize the
// Binary Indexed Tree
int[] BITree = new int[n + 1];
for (int i = 0; i <= n; i++)
BITree[i] = 0;
// Store the actual values in
// BITree[] using update()
for (int i = 0; i < n; i++)
updateBIT(BITree, n, i, arr[i]);
return BITree;
}
// Function to obtian and return
// the index of lower_bound of k
static int getLowerBound(int BITree[],
int[] arr, int n, int k)
{
int lb = -1;
int l = 0, r = n - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (getSum(BITree, mid) >= k) {
r = mid - 1;
lb = mid;
}
else
l = mid + 1;
}
return lb;
}
static void performQueries(int A[], int n, int q[][])
{
// Store the Binary Indexed Tree
int[] BITree = constructBITree(A, n);
// Solve each query in Q
for (int i = 0; i < q.length; i++) {
int id = q[i][0];
if (id == 1) {
int idx = q[i][1];
int val = q[i][2];
A[idx] += val;
// Update the values of all
// ancestors of idx
updateBIT(BITree, n, idx, val);
}
else {
int k = q[i][1];
int lb = getLowerBound(
BITree, A, n, k);
System.out.println(lb);
}
}
}
// Driver Code
public static void main(String[] args)
{
int A[] = { 1, 2, 3, 5, 8 };
int n = A.length;
int[][] q = { { 1, 0, 2 },
{ 2, 5 },
{ 1, 3, 5 } };
performQueries(A, n, q);
}
}
Python3
# Python3 program to implement
# the above appraoch
# Function to calculate and return
# the sum of arr[0..index]
def getSum(BITree, index):
ans = 0
index += 1
# Traverse ancestors
# of BITree[index]
while (index > 0):
# Update the sum of current
# element of BIT to ans
ans += BITree[index]
# Update index to that
# of the parent node in
# getSum() view by
# subtracting LSB(Least
# Significant Bit)
index -= index & (-index)
return ans
# Function to update the
# Binary Index Tree by
# replacing all ancestores
# of index by their respective
# sum with val
def updateBIT(BITree, n,
index, val):
index = index + 1
# Traverse all ancestors
# and sum with 'val'.
while (index <= n):
# Add 'val' to current
# node of BIT
BITree[index] += val
# Update index to that
# of the parent node in
# updateBit() view by
# adding LSB(Least
# Significant Bit)
index += index & (-index)
# Function to construct the Binary
# Indexed Tree for the given array
def constructBITree(arr, n):
# Initialize the
# Binary Indexed Tree
BITree = [0] * (n + 1)
for i in range(n + 1):
BITree[i] = 0
# Store the actual values in
# BITree[] using update()
for i in range(n):
updateBIT(BITree, n, i, arr[i])
return BITree
# Function to obtian and return
# the index of lower_bound of k
def getLowerBound(BITree, arr,
n, k):
lb = -1
l = 0
r = n - 1
while (l <= r):
mid = l + (r - l) // 2
if (getSum(BITree,
mid) >= k):
r = mid - 1
lb = mid
else:
l = mid + 1
return lb
def performQueries(A, n, q):
# Store the Binary Indexed Tree
BITree = constructBITree(A, n)
# Solve each query in Q
for i in range(len(q)):
id = q[i][0]
if (id == 1):
idx = q[i][1]
val = q[i][2]
A[idx] += val
# Update the values of all
# ancestors of idx
updateBIT(BITree, n,
idx, val)
else:
k = q[i][1]
lb = getLowerBound(BITree,
A, n, k)
print(lb)
# Driver Code
if __name__ == "__main__":
A = [1, 2, 3, 5, 8]
n = len(A)
q = [[1, 0, 2],
[2, 5, 0],
[1, 3, 5]]
performQueries(A, n, q)
# This code is contributed by Chitranayal
C#
// C# program to implement
// the above appraoch
using System;
class GFG{
// Function to calculate and return
// the sum of arr[0..index]
static int getSum(int []BITree,
int index)
{
int ans = 0;
index += 1;
// Traverse ancestors
// of BITree[index]
while (index > 0)
{
// Update the sum of current
// element of BIT to ans
ans += BITree[index];
// Update index to that
// of the parent node in
// getSum() view by
// subtracting LSB(Least
// Significant Bit)
index -= index & (-index);
}
return ans;
}
// Function to update the Binary Index
// Tree by replacing all ancestores of
// index by their respective sum with val
static void updateBIT(int []BITree,
int n, int index,
int val)
{
index = index + 1;
// Traverse all ancestors
// and sum with 'val'.
while (index <= n)
{
// Add 'val' to current
// node of BIT
BITree[index] += val;
// Update index to that
// of the parent node in
// updateBit() view by
// adding LSB(Least
// Significant Bit)
index += index & (-index);
}
}
// Function to construct the Binary
// Indexed Tree for the given array
static int[] constructBITree(int []arr,
int n)
{
// Initialize the
// Binary Indexed Tree
int[] BITree = new int[n + 1];
for(int i = 0; i <= n; i++)
BITree[i] = 0;
// Store the actual values in
// BITree[] using update()
for(int i = 0; i < n; i++)
updateBIT(BITree, n, i, arr[i]);
return BITree;
}
// Function to obtian and return
// the index of lower_bound of k
static int getLowerBound(int []BITree,
int[] arr, int n,
int k)
{
int lb = -1;
int l = 0, r = n - 1;
while (l <= r)
{
int mid = l + (r - l) / 2;
if (getSum(BITree, mid) >= k)
{
r = mid - 1;
lb = mid;
}
else
l = mid + 1;
}
return lb;
}
static void performQueries(int []A, int n,
int [,]q)
{
// Store the Binary Indexed Tree
int[] BITree = constructBITree(A, n);
// Solve each query in Q
for(int i = 0; i < q.GetLength(0); i++)
{
int id = q[i, 0];
if (id == 1)
{
int idx = q[i, 1];
int val = q[i, 2];
A[idx] += val;
// Update the values of all
// ancestors of idx
updateBIT(BITree, n, idx, val);
}
else
{
int k = q[i, 1];
int lb = getLowerBound(BITree,
A, n, k);
Console.WriteLine(lb);
}
}
}
// Driver Code
public static void Main(String[] args)
{
int []A = { 1, 2, 3, 5, 8 };
int n = A.Length;
int [,]q = { { 1, 0, 2 },
{ 2, 5, 0 },
{ 1, 3, 5 } };
performQueries(A, n, q);
}
}
// This code is contributed by 29AjayKumar
1
时间复杂度: O(Q *(logN) 2 )
辅助空间: O(N)