看下面这个问题(动态连续和查询):

有一个数组A(长度为n),要求进行两种操作:
add(i,x):让Ai增大x;
query(a,b):询问Aa+Aa+1+...+Ab的和;
若进行模拟,则每次query操作的最坏的时间复杂度为O(n),在n较大时速度较慢。用前缀和也不能提高效率(每次add操作最坏为O(n))。有一种数据结构,可以在O(n)时间里初始化,用O(logn)的速度执行add操作或查询前缀和,从而执行query操作。
首先,我们来介绍“lowbit”。对于一个数x,lowbit(x)是x的二进制里最右面的1所代表的数字,例如lowbit(20)=4,因为20的二进制为10100,最右面的1代表4。怎样计算lowbit呢?很简单,lowbit(x)=x&-x。这是因为负数是用补码保存的,-x就相当于(~x)+1。例(用8位计算):
 20=(00010100)
-20=(11101100)
现在我们来介绍二叉索引树。二叉索引树在程序中也是用数组来保存的。
(画得难看请见谅)
图中,深灰色方块代表树中的结点(结点0为虚拟结点),灰色线段代表树中的边。这些边并不需要显式保存;对于一个节点x,若它是父结点的左子结点,则父结点编号为x-lowbit(x),否则为x+lowbit(x)。图中的每个结点左侧都有一个白色长条(包括它自己),如结点4的长条为1~4,节点3的长条为3~3。不难发现,结点x的长条为(x-lowbit(x)+1)~x。
然后,我们用一个数组S储存每个结点的白色长条内的所有数的和。例如,S4=A1+A2+A3+A4。这样,就可以使用一个辅助的前缀和数组,在O(n)时间内从左到右初始化S数组。代码如下:
 
 
 int n;
 int S[maxn],A[mxan],S1[maxn];
 int begin()
 {
     memset(S1,,sizeof(S1));
     ;i<=n;i++)
     {
         S1[i]=S1[i-]+A[i];
         S[i]=S1[i]-S1[i-lowbit(i)];
     }
 }
最后让我们来实现add操作和查询操作。对于某个add操作的结点i,它的修改会影响到那些结点呢?很显然,在它下面的结点(lowbit比它小)不会受到影响,在它左边的结点也不会受到影响,所以只需要考虑在它右边且lowbit比它大的第一个结点,这个结点的白色长条一定覆盖x。很显然,这个结点的编号为i+lowbit(i)。
接下来,x结点不需要考虑了,让我们来考虑i+lowbit(i)结点。与上面一样,只需要考虑在它右边且lowbit比它大的第一个结点,所以只需要让i+=lowbit(i)。代码如下:
 void add(int i,int x)
 {
     //若需要其他操作,可以加一句:
     //A[i]+=x;
     while(i<=n)
     {
         S[i]+=x;i+=lowbit(i);
     }
 }

查询前缀和的方法与之类似,只是i+=lowbit(i);改成了i-=lowbit(i);这里不再介绍证明方法,与上面类似。代码如下:

 int query2(int i)
 {
     ;
     )
     {
         sum+=S[i];i-=lowbit(i);
     }
     return sum;
 }
 int query(int l,int r)
 {
     );
 }
最后,若有建议请提出。

C++实用数据结构:二叉索引树的更多相关文章

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

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

  2. 二叉索引树BIT

    定义     二叉索引树,binary index tree,又名树状数组,或Fenwick Tree,因为本算法由Fenwick创造.     对于数组A,定义Query(i,j) = Ai +Ai ...

  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. 二叉索引树,LA2191,LA5902,LA4329

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

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

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

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

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

随机推荐

  1. charindex的用法

    declare @str nvarchar(50);set @str='462,464,2';select @str as '字符串'select len(@str) as '字符长度' select ...

  2. 写一个函数reverseList,该函数能够接受一个List,然后把该List 倒序排列。 例如:  List list = new ArrayList();  list.add(“Hello”);  list.add(“World”);  list.add(“Learn”); //此时list 为Hello World Learn  reverseList

    package homework004; import java.util.ArrayList; import java.util.List; public class Daoxu { public ...

  3. Effective C++ 第二版 17)operator=检查自己 18)接口完整 19)成员和友元函数

    条款17 在operator=中检查给自己赋值的情况 1 2 3 class  X { ... }; X a; a = a;  // a 赋值给自己 >赋值给自己make no sense, 但 ...

  4. android学习日记17--Gallery(画廊视图)

    一.Gallery 1.简述 Gallery有道翻译为画廊,就叫它画廊控件,主要用来可切换的图片展示,左右滑动可以选择上一张或下一张图片. 个人感觉蛮实用的,不过google貌似不推荐使用啊! 2.常 ...

  5. 动态追踪技术(中) - Dtrace、SystemTap、火焰图

    http://openresty.org/cn/presentations.html http://weibo.com/agentzh?is_all=1 http://openresty.org/po ...

  6. NPOI导出多表头Execl(通过html表格遍历表头)

    关于NPOI的相关信息,我想博客园已经有很多了,而且NPOI导出Execl的文章和例子也很多,但导出多表头缺蛮少的:今天要讲的通过自己画html表格:通过html表格来导出自定义的多表头: 先来看要实 ...

  7. 第一章 02 谈谈static关键词

    引文一下吧 http://blog.csdn.net/hackbuteer1/article/details/7487694 一.static在C语言中的含义 1.静态变量作用范围在一个文件内,程序开 ...

  8. Objective-C中系统宏的用法总结

    先说一下本文中会提到的内容:##,__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__等 宏变量: 先举一个例子,会用到上面这些宏: #define mypri ...

  9. 深入理解计算机系统第二版习题解答CSAPP 2.10

    对于任一位向量a,有a ^ a = 0.考虑下面的程序: void inplace_swap(int *x, int *y) { *y = *x ^ *y; *x = *x ^ *y; *y = *x ...

  10. Redis & Sentinel 安装脚本

    #!/bin/bash # 判断是否为root用户,不是root用户提示退出 if [[ $EUID -ne 0 ]]; then    echo "This script. must be ...