Fenwick Tree / Binary Indexed Tree

Motivation:

Given a 1D array of n elements. [2, 5, -1, 3, 6]

range sum query: what's the sum from 2nd element to 4th element query(2, 4)? 5 + (-1) + 3 = 7

Native implementation: O(n) per query.

Use DP to pre-compute the prefix sums in O(n), [2, 5, -1, 3, 6] -> [2, 7, 6, 9, 15]

reduce query to O(1). query(2, 4) = sums(n1....n4) - sums(n1....n1) = sums[4-1] - sums[1-1] = 9 - 2 = 7

what if the value of elements can change? O(n) 

 

Fenwick tree was proposed to solve the prefix sum problem.

The idea is to store partial sum in each node and get total sum by traversing  the tree from leaf to root. the tree has a height of log(n)

Query: O(log(n))

Update: O(log(n))

class FenwickTree {
public:
    FenwickTree(int n): sums_(n+1, 0) {}
    
    void update(int i, int delta) {
        while (i < sums_.size()) {
            sums_[i] += delta;
            i += lowbit(i);
        }
    }
    
    int query(int i) const {
        int sum = 0;
        while (i > 0) {
            sum += sums_[i];
            i -= lowbit(i);
        }
        return sum;
    }
private:
    static inline int lowbit(int x) { return x & (-x); }
    vector<int> sums_;
};

 

转载于:https://www.cnblogs.com/ruruozhenhao/p/10035298.html

Fenwick Tree,又称为树状数组(Binary Indexed Tree),是一种基于数组实现的数据结构,用于高效地动态维护前缀和。它可以在O(logn)的时间内完成以下操作:更新某个元素的值,查询某个区间的和。Fenwick Tree的实现原理是将数组分解为一系列的区间和,每个区间和保存在树状数组的相应位置上。通过使用二进制的技巧,可以高效地计算每个区间和。: ``` public class FenWickTree { private int[] values; private int[] bit; public FenWickTree(int length) { values = new int[length]; bit = new int[length + 1]; } public void setValues(int index, int value) { values[index = value; index += 1; while (index < bit.length) { bit[index += value; index += index & -index; } } public int getSum(int index) { int sum = 0; while (index > 0) { sum += bit[index]; index -= index & -index; } return sum; } } ``` 以上代码展示了如何使用Fenwick Tree实现动态维护前缀和的功能。其中setValues()方法用于更新某个元素的值,getSum()方法用于查询某个区间的和。 另外,Fenwick Tree也可以用来解决区间修改的问题。对于元素的修改,我们可以视为区间查询的逆过程,通过从叶节点开始向上更新父节点,依次对每个父节点进行相同的修改操作。具体的实现可以参考下面的示例代码: ``` class FenwickTree { private int[] tree; public FenwickTree(int n) { tree = new int[n + 1]; } public int lowbit(int x) { return x & (-x); } public void add(int i, int val) { while (i < tree.length) { tree[i += val; i += lowbit(i); } } public int query(int i) { int res = 0; while (i > 0) { res += tree[i]; i -= lowbit(i); } return res; } } ``` 这段代码展示了如何使用Fenwick Tree解决区间修改的问题。add()方法用于修改某个元素,query()方法用于查询某个区间的和。 综上所述,Fenwick Tree是一种用于高效地动态维护前缀和的数据结构,可以在O(logn)的时间内完成更新和查询操作。同时,它也可以应用于区间修改的问题。 #### 引用[.reference_title] - *1* *3* [【数据结构与算法】树状数组](https://blog.csdn.net/zzy_NIC/article/details/130616434)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [6.10 Fenwick树](https://blog.csdn.net/m0_66201040/article/details/122923027)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值