Fenwick tree是一种允许两种操作的数据结构(您可以通过更多操作来扩充它):
update(index, value)
query(index)
这两个操作都在O(log(n))
中,其中n
是数组的大小。理解如何进行操作及其背后的逻辑,我没有任何问题。
我的问题是如何从数组初始化Fenwick树。很明显,我可以通过O(nlog(n))
次n
调用update(i, arr[i])
来实现这一目标,但有没有办法在O(n)
中初始化它。
如果维基百科告诉您可以在nlog(n)
中初始化,为什么还要问这个?因为这篇文章是如此简陋,我不确定它是否是人们能够实现的最佳复杂性。还可以通过逐个填充堆来完成初始堆创建,并且可以在O(nlog(n))
中实现与O(n)
中的智能堆初始化相比,这让我希望在Fenwick树中可以完成类似的操作。
答案 0 :(得分:23)
[EDIT: I had things "upside-down" -- fixed now!]
Yes. Loop through the n array items in increasing index order, always adding the sum only to the next smallest index that it should be added to, instead of to all of them:
for i = 1 to n:
j = i + (i & -i) # Finds next higher index that this value should contribute to
if j <= n:
x[j] += x[i]
This works because although every value contributes to several range sums, after processing the bottommost range sum that the value contributes to (which actually requires no "processing", since the sum is already in there), we no longer need to maintain its separate identity -- it can safely be merged with all other values that contribute to the remaining range sums.
TTBOMK this algorithm is "new" -- but then I haven't looked very hard ;)
答案 1 :(得分:0)
这是Java实现:
public BIT(long[] nums) {
bit = new long[nums.length + 1]; //one-indexed
for (int i = 1; i <= nums.length; i++) {
bit[i] += nums[i - 1]; //update node
if (i + (i & -i) <= nums.length) {
bit[i + (i & -i)] += bit[i]; //update parent
}
}
}
与j_random_hacker的帖子相同的基本思想:我们使用以下属性更新当前节点和下一个更高的父节点:所有子节点将始终在其各自的父节点之前被访问