Binary Indexed Tree 主要是为了存储数组前缀或或后缀和,以便计算任意一段的和。其优势在于可以常数时间处理更新(如果不需要更新直接用一个数组存储所有前缀/后缀和即可)。
空间复杂度O(n). 其中每个元素,存储的是数组中一段(起始元素看作为1而非0)的和:

假设这个元素下标为i,找到i的最低位1,从最低位1开始的低部表示的是长度,去除最低位1剩下的部分加上1表示的是起始位置,例如:

8二进制表示为100

最低位1也是最高位,从1开始的低部也即100本身,因此长度为8.

去除1以后,剩下为0,加上1以后为1。所以sum[8]表示的是从第1个元素开始的8个元素的和.

又比如11的二进制表示为1011

最低位1,因此表示的段长度为1。

去掉1以后剩下部分为1010,因此起始元素为第11个元素。所以sum[11]表示的就是原数组的第11个元素。

求i的最低位1(LSB)可以使用如下位运算:

i & (-i)

求1..i之和,以11为例

sum[11] = sum[8] + sum[10] + sum[11] 也即 0..8之和 + 9, 10之和 + 11。我们可以从最低位开始相加:

    int sum = ;
while (i > )
sum += A[i], i -= LSB(i);
return sum;

更新i的值,需要更新所有受影响的和,从sum[i]开始,逐渐扩大i的范围

    while (i < SIZE) 

        A[i] += k, i += LSB(i);

比如元素5被更新了,5表示为2进制是101,

那么我们首先更新元素5本身,

然后,5所在的2个元素的小区间:5,6也需要被更新也即 5 + LSB(5) = 6 被更新。

然后,更新5所在的更大的区间,1..8,也即: 6 + LSB(6) = 8。注意,并不存在5..8这样一个单独的4元素区间。每个区间的后半部分可以用这个区间减去前半部分得到:sum 5..8 = sum[8] – sum[4]。

上述代码来自Wiki

最后,求任意区间i..j的值可以由sum[j] – sum[i]得到。

以LeetCode 307. Range Sum Query – Mutable为例,以下为源码:

class NumArray{
public:
// Binary Index Tree (Fenwick Tree)
NumArray(vector<int> nums) {
_nums = vector<int>(nums.size(), );
sums = vector<int>(nums.size() + , );
len = sums.size();
for(int i = ; i < len - ; i++){
update(i, nums[i]);
}
} void update(int i, int val) {
int d = val - _nums[i];
_nums[i++] = val;
while(i < len){
sums[i] += d;
i += LBS(i);
}
} // [i+1, j+1] inclusive, so it should be sum[j+1] - sum[i]
int sumRange(int i, int j) {
return sumRange(++j) - sumRange(i);
}
private:
vector<int> sums;
vector<int> _nums;
int len;
inline int LBS(int &i){
return i & (-i);
} inline int sumRange(int i){
int sum = ;
while(i){
sum += sums[i];
i -= LBS(i);
}
return sum;
}
};

Binary Indexed Tree (Fenwick Tree)的更多相关文章

  1. 树状数组 Binary Indexed Tree/Fenwick Tree

    2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...

  2. 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 2n ...

  3. Binary Indexed Tree

    我借鉴了这个视频中的讲解的填坑法,我认为非常易于理解.有FQ能力和基本英语听力能力请直接去看视频,并不需要继续阅读. naive 算法 考虑一个这样的场景: 给定一个int数组, 我们想知道它的连续子 ...

  4. Leetcode: Range Sum Query 2D - Mutable && Summary: Binary Indexed Tree

    Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...

  5. SRM 627 D1L2GraphInversionsDFS查找指定长度的所有路径 Binary indexed tree (BIT)

    题目:http://community.topcoder.com/stat?c=problem_statement&pm=13275&rd=16008 由于图中边数不多,选择DFS遍历 ...

  6. 树状数组(Binary Indexed Tree,BIT)

    树状数组(Binary Indexed Tree) 前面几篇文章我们分享的都是关于区间求和问题的几种解决方案,同时也介绍了线段树这样的数据结构,我们从中可以体会到合理解决方案带来的便利,对于大部分区间 ...

  7. Hdu5921 Binary Indexed Tree

    Hdu5921 Binary Indexed Tree 思路 计数问题,题目重点在于二进制下1的次数的统计,很多题解用了数位DP来辅助计算,定义g(i)表示i的二进制中1的个数, $ans = \su ...

  8. Binary Indexed Tree 总结

    特点 1. 针对 数组连续子序列累加和 问题(需要进行频繁的 update.sum 操作): 2. 并非是树型结构,只是逻辑上层次分明: 3. 可以通过 填坑法 来理解: 4. 中心思想:每一个整数都 ...

  9. 树状数组(Binary Indexed Tree)

    树状数组(Binary Indexed Tree,BIT) 是能够完成下述操作的数据结构. 给一个初始值全为 0 的数列 a1, a2, ..., an (1)给定 i,计算 a1+a2+...+ai ...

随机推荐

  1. 组合数计算-java

    排列组合是计算应用经常使用的算法,通常使用递归的方式计算,但是由于n!的过于大,暴力计算很不明智.一般使用以下两种方式计算. 一,递归的思想:假设m中取n个数计算排列组合数,表示为comb(m,n). ...

  2. August 13th 2017 Week 33rd Sunday

    The best accessory a girl can own is confidence. 女生最好的饰品就是自信. Only when we have our own ideas and on ...

  3. solrCloud相关的管理命令

    创建新集群(创建一个索引库) http://192.168.72.141:8080/solr/admin/collections?action=CREATE&name=collection2& ...

  4. JavaScript设计模式导学

    如何成为一名合格的工程师? 作为一名合格的工程师,不仅需要懂代码,还要懂设计,一名合格工程师的必备条件: 前端开发有一定的设计能力,一般三年开发经验的同学,面试必须考设计能力 成为项目技术负责人,设计 ...

  5. 粒子群优化算法PSO及matlab实现

    算法学习自:MATLAB与机器学习教学视频 1.粒子群优化算法概述 粒子群优化(PSO, particle swarm optimization)算法是计算智能领域,除了蚁群算法,鱼群算法之外的一种群 ...

  6. 通过iframe标签绕过csp

    iframe.php代码如下: allow-popups开启时,window.open就可以打开新的窗口. 看csp规则,默认是在当前域内,如果这是一个ctf题的话,就很简单了,window.loca ...

  7. Java50道经典习题-程序21 求阶乘

    题目:求1+2!+3!+...+20!的和分析:使用递归求解 0的阶乘和1的阶乘都为1 public class Prog21{ public static void main(String[] ar ...

  8. 【JavaScript】插件参数的写法

    就是实现复制的一个过程 (function() { var Explode = function(container, params) { 'use strict'; var n = this; if ...

  9. WEB安全 php+mysql5注入防御(二)

    第四天: 一.新的注入函数: ascii() substring("string",n,m)                     n>=1 limit n,m      ...

  10. scrapy(1)win安装

    scrapy是爬虫的一个框架,目前支持python2,python3暂不支持 首先win安装环境: 1.如果你比较幸运,直接pip install scrapy就能成功 2.如果你像我一样,安装过程中 ...