定义

    二叉索引树,binary index tree,又名树状数组,或Fenwick Tree,因为本算法由Fenwick创造。

    对于数组A,定义Query(i,j) = Ai +Ai+1 + … + Aj.

    比较好的做法:使用前缀和,Sum(j) – Sum(i-1)即可得到Query(i,j)

    BIT即为解决此类区间查询而大展身手,因为预处理时间为O(n),之后的查询时间为O(1),是属于典型的在线算法(关于在线算法,通俗地可以理解为,做一次预处理,提供多次“服务”——比如多次Query(i,j))。

Lowbit(nature)

    首先,定位lowbit(natural)为自然数(即1,2,3…n)的二进制形式中最右边出现1的值。

    比如:4 = 100,lowbit(4) = 4;36 = 100100,lowbit(36) = 4.

    自然数在二进制形式下,有如下的性质:

    Lowbit为1的自然数为1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31…d = 2

    Lowbit为2的自然数为2,6,10,14,18,22,26,30,… d = 4

    Lowbit为3的自然数为4,12,20,28… d=8

    Lowbit为4的自然数为8,32

    直接上刘汝佳的算法竞赛入门竞赛经典中的图片:

    

    树状性质:对于节点i,如果他是左子结点,那么父节点的编号就是i+lowbit(i);如果它是右子节点,那么父节点的编号是i-lowbit(i)。

    令数组C为:

     Ci = Ai-lowbit(i)+1+A i-lowbit(i)+2+…Ai

    即从最左边的孩子,到自身的和,如C12 = A9(上图中最左边的儿子)+A10+A11+A12,C6=A5+A6。

    计算前缀和Sum(i)的计算:

    顺着节点i往左走,边走边“往上爬”,把经过的Ci 累加起来即可。

API

    l lowbit(idx)

      求A[idx]的低位

    l Sum(i)

     求区间1,i的前缀和

    l Add(idx,value)

      使节点idx的值增加value;

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Algorithms.Data_Structure
{
/// <summary>
/// 二叉索引树(树状数组:Fenwick Tree)
/// </summary>
public class BinaryIndexedTree
{
/// <summary>
/// 处理的数组
/// </summary>
private List<int> array; /// <summary>
/// 二叉前缀和
/// </summary>
private List<int> tree; /// <summary>
/// 个数
/// </summary>
private int n; public BinaryIndexedTree(int[] array)
{
this.array = new List<int>(array);
this.n = this.array.Count; PreProcessing();
} /// <summary>
/// 预处理函数:每次增加数值
/// </summary>
private void PreProcessing()
{
tree = new List<int>(n);
for (int ii = 0; ii < n; ii++)
{
tree.Add(0);
} for (int ii = 1; ii < n; ii++)
{
Update(ii, array[ii]);
}
} /// <summary>
/// 二进制形式中的最右边的1所对应的值,如38288 = 1001010110010000 ,则返回16
/// </summary>
/// <param name="idx"></param>
private int lowbit(int idx)
{
return idx & (-idx);
} /// <summary>
/// 在x处加v
/// </summary>
/// <param name="idx">数组的索引,从1开始计数</param>
/// <param name="v">值</param>
public void Update(int idx, int v)
{
while (idx < n)
{
tree[idx] += v;
idx += lowbit(idx); //left's parent
}
} /// <summary>
/// 从0到x求和
/// </summary>
/// <param name="idx">索引,从1开始计数</param>
/// <returns>求和结果</returns>
public int Sum(int idx)
{
int ret = 0;
while (idx > 0)
{
ret += tree[idx];
idx -= lowbit(idx); // right's parent
}
return ret;
}
}
}

Test:

class Program
{
static void Main(string[] args)
{
BinaryIndexedTree bit = new BinaryIndexedTree(new int[] { 0, 1, 2, 3, 4, 5 }); //从1开始计数
Console.WriteLine(bit.Sum(5));//15
bit.Update(4, 23);
Console.WriteLine(bit.Sum(5));//38
}
}

二叉索引树BIT的更多相关文章

  1. 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)

    在网上找到一篇非常不错的树状数组的博客,拿来转载,原文地址. 树状数组 最新看了一下区间的查询与修改的知识,最主要看到的是树状数组(BIT),以前感觉好高大上的东西,其实也不过就这么简单而已. 我们有 ...

  2. C++实用数据结构:二叉索引树

    看下面这个问题(动态连续和查询): 有一个数组A(长度为n),要求进行两种操作: add(i,x):让Ai增大x: query(a,b):询问Aa+Aa+1+...+Ab的和: 若进行模拟,则每次qu ...

  3. POJ 3321 Apple Tree dfs+二叉索引树

    题目:http://poj.org/problem?id=3321 动态更新某个元素,并且求和,显然是二叉索引树,但是节点的标号不连续,二叉索引树必须是连续的,所以需要转化成连续的,多叉树的形状已经建 ...

  4. NYOJ 116 士兵杀敌(二)(二叉索引树)

    http://acm.nyist.net/JudgeOnline/problem.php?pid=116 题意: 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的 ...

  5. HDU 1166 敌兵布阵(线段树 or 二叉索引树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=50000),表示敌人有 ...

  6. 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)

    [概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...

  7. 树状数组(二叉索引树 BIT Fenwick树) *【一维基础模板】(查询区间和+修改更新)

    刘汝佳:<训练指南>Page(194) #include <stdio.h> #include <string.h> #include <stdlib.h&g ...

  8. 二叉索引树,LA2191,LA5902,LA4329

    利用了二进制,二分的思想的一个很巧妙的数据结构,一个lowbit(x):二进制表示下的最右边的一个1开始对应的数值. 那么如果一个节点的为x左孩子,父亲节点就是 x + lowbit(x),如果是右孩 ...

  9. 1.红黑树和自平衡二叉(查找)树区别 2.红黑树与B树的区别

    1.红黑树和自平衡二叉(查找)树区别 1.红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单. 2.平衡 ...

随机推荐

  1. Spring AOP使用整理:自动代理以及AOP命令空间

    三.自动代理的实现 1.使用BeanNameAutoProxyCreator 通过Bean的name属性自动生成代理Bean. <bean class="org.springframe ...

  2. android webview删除缓存

    [1].[代码] 删除保存于手机上的缓存. 跳至 [1] [2] [3] 01 // clear the cache before time numDays     02 private int cl ...

  3. Linux下网络故障诊断

    导读 由于实现网络服务器的层次结构比较多,因此当网络出现故障时,解决起来比较复杂.下面由我来为大家详细介绍Linux系统中可能出现的一些网络问题,如网卡硬件问题.网络配置问题.驱动程序问题,以及网络层 ...

  4. java 异常处理 Throwable Error 和Exception

    Java异常类层次结构图:       异常的英文单词是exception,字面翻译就是“意外.例外”的意思,也就是非正常情况.事实上,异常本质上是程序上的错误,包括程序逻辑错误和系统错误. 比如使用 ...

  5. 【leetcode】Letter Combinations of a Phone Number

    Letter Combinations of a Phone Number Given a digit string, return all possible letter combinations ...

  6. 使用WebDriver遇到的那些坑(转)

    http://www.huangbowen.net/blog/2013/06/25/practice-of-webdriver/ 在做web项目的自动化端到端测试时主要使用的是Selenium Web ...

  7. 24.栈的push和pop序列[StackPushPopSequence]

    [题目] 输入两个整数序列.其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序.为了简单起见,我们假设push序列的任意两个整数都是不相等的. 比如输入的push序列是1.2 ...

  8. cmd的rd命令简单解析

    我们知道在Windows下cmd命令行中"rd 文件夹名称"可以删除空目录,"del 文件名"可以删除文件,那么怎么删除一个非空文件夹呢,命令如下: 比如删除文 ...

  9. 基于Delphi的三层数据库系统的实现方法

    基于Delphi的三层数据库系统的实现方法   1  引言 当前的数据库应用系统中,按其结构划分为两类,一类是两层结构的数据库应系统,另一类是多层结构的数据库应用系统. 两层结构的数据库应用系统包括客 ...

  10. Java for LeetCode 027 Remove Element

    Given an array and a value, remove all instances of that value in place and return the new length. T ...