📌  相关文章
📜  使用Fenwick树从前缀求和数组中查找K的下界并进行更新

📅  最后修改于: 2021-04-23 20:21:25             🧑  作者: Mango

给定一个由非负整数组成的数组A []和由以下两种类型的查询组成的矩阵Q [] []

  • (1,l,val):将A [l]更新为A [l] + val
  • (2,K):查找K的LOWER_BOUND A []的前缀求和阵列英寸如果lower_bound不存在,请打印-1。

第二种类型的每个查询的任务是打印值Klower_bound的索引。

例子:

天真的方法:
最简单的方法是首先构建给定数组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)