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

📅  最后修改于: 2023-12-03 14:49:22.138000             🧑  作者: Mango

从前缀和数组中查找K的下界,并使用Fenwick树进行更新

在计算一个数据的前缀和数组时,有时我们需要在这个数组中查找某个值K的下界,即第一个大于或等于K的元素的位置。

本文将介绍如何通过前缀和数组快速查找K的下界,并使用Fenwick树进行更新。

前缀和数组

前缀和数组是指对一个数据对应的前缀值进行求和以后得到的一个数组。例如,对于数组[1, 2, 3, 4, 5],它的前缀和数组为[1, 3, 6, 10, 15]。

前缀和数组的一个重要用途是可以在O(1)的时间内计算出一个区间内的元素和。例如,对于区间[2, 4],我们可以通过前缀和数组快速计算出它的元素和为10 - 3 + 2 = 9。

查找K的下界

我们可以通过二分查找的方法在前缀和数组中查找K的下界。具体的做法是:在数组中查找第一个大于或等于K的元素的位置。

具体实现过程可以参考下面的代码:

def find_first_greater_or_equal(nums, k):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] < k:
            left = mid + 1
        else:
            right = mid - 1
    return left

上面的代码中,我们用二分查找的方法在数组中查找第一个大于或等于K的元素的位置。由于left是数组中第一个不小于K的元素的位置,因此它就是我们要查找的K的下界。

使用Fenwick树进行更新

Fenwick树是一种能够在O(logN)时间内支持单点修改和前缀求和的数据结构。它的主要思想是将每个元素重新排列,使得每个元素的下标只包含二进制中的最低的1。

Fenwick树支持两种查询操作:单点查询和前缀查询。单点查询用于查询某个位置上的元素,它的时间复杂度是O(logN)。前缀查询用于查询前缀和,它的时间复杂度是O(logN)。

下面是Fenwick树的代码实现:

class FenwickTree:
    def __init__(self, n):
        self.nums = [0] * (n + 1)

    def update(self, i, delta):
        while i < len(self.nums):
            self.nums[i] += delta
            i += i & -i

    def query(self, i):
        res = 0
        while i > 0:
            res += self.nums[i]
            i -= i & -i
        return res

在使用Fenwick树对前缀和数组进行更新时,我们需要先找到K的下界,然后对从下界到数组末尾的所有元素进行更新。具体的代码如下所示:

tree = FenwickTree(len(nums))
index = find_first_greater_or_equal(nums, k)
while index < len(nums):
    tree.update(index + 1, delta)
    index += 1

上面的代码中,我们用find_first_greater_or_equal函数找到了K的下界。然后我们使用Fenwick树对从下界到数组末尾的所有元素进行更新。

总结

本文介绍了如何通过前缀和数组快速查找K的下界,并使用Fenwick树进行更新。前缀和数组可用于快速计算一个区间内的元素和,二分查找则可用于在前缀和数组中查找K的下界。Fenwick树则可用于在O(logN)时间内支持前缀查询和单点修改。