二叉索引树BIT

时间:2021-10-23 05:07:37

定义

    二叉索引树,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

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

二叉索引树BIT

    

    树状性质:对于节点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&plus;&plus;实用数据结构:二叉索引树

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

  3. POJ 3321 Apple Tree dfs&plus;二叉索引树

    题目: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树) &ast;【一维基础模板】(查询区间和&plus;修改更新)

    刘汝佳:<训练指南>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&period;红黑树和自平衡二叉&lpar;查找&rpar;树区别 2&period;红黑树与B树的区别

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

随机推荐

  1. Android之网络数据存储

    一.网络保存数据介绍 可以使用网络来保存数据,在需要的时候从网络上获取数据,进而显示在App中. 用网络保存数据的方法有很多种,对于不同的网络数据采用不同的上传与获取方法. 本文利用LeanCloud ...

  2. DNS解析流程

    DNS简单来说就是进行域名和IP的转换,那该如何转换呢?既然要转换,肯定有转换表,那表应该存 哪个服务器上,怎样去请求域名服务器来进行转换,所以,这个转换的过程都是什么.而面试的时 经常会有这道题:当 ...

  3. IEEE二进制浮点数算术标准学习

    看到有网上有个项目是要求将浮点数用二进制表示出来,需要用IEEE754标准,查了查维基和深入理解计算机系统,重新学习了一遍浮点数在计算机中的表示和内存中的存储, 先简单的做个笔记,后面需要更深入的理解 ...

  4. 用非管理员权限启动主程序,并用管理员权限启动子程序,导致WM&lowbar;COPYDATA消息发送失败的问题

    问题描述 :     用非管理员权限启动dzh,dzh再启动dtssm,由于dtssm的配置文件app.manifest 中设置了requireAdministrator,导致dtssm总是以管理员权 ...

  5. windows下exfat无法写入修复

    为了可以实现mac与windows文件共享,把移动硬盘格式化为exfat了,但是在osx中放入文件后,在windows上紧进行读取写入时出现错误,提示使用chkdsk进行修正,以下是修正步骤. ①wi ...

  6. HttpReceiveRequestEntityBody 使用应注意的地方

    如果EntityBody数据很大,调用此函数是不能完全接收全部数据的,我们不能简单的判断 1: BYTE* pBuffer = new BYTE[4096]; 2: ZeroMemory(pBuffe ...

  7. 基于注解的Dubbo服务配置

      基于注解的Dubbo服务配置可以大大减少dubbo xml配置文件中的Service配置量,主要步骤如下:   一.服务提供方   1. Dubbo配置文件中增加Dubbo注解扫描 <!-- ...

  8. String&comma;StringBuffer与StringBuilder的区别&vert;线程安全与线程不安全

    https://www.cnblogs.com/xingzc/p/6277581.html

  9. python实现Content-Type类型为application&sol;x-www-form-urlencoded发送POST请求

    周日晚上接到公司的电话需要通过新榜的接口拿下微博热搜数据,拿到接口文档看了下很简单的一个post请求,主要根据时间段来获取热搜数据. 在实际编码的过程中经常遇到header的Content-Type的 ...

  10. 转: C&num; 的结构剖析

    原文链接:http://www.cnblogs.com/jiajiayuan/archive/2011/09/20/2181582.html 本文意在巩固基础知识,并不是对其进行深入剖析,还望理解.本 ...