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

有一个数组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. iOS 分类和继承

    iOS 中分类(Categories) 和 继承(Inherit)有相同的功能,但在一些细节上又有差异,简单介绍一下两者的异同. 分类可以在不知道系统类源代码的情况下,为这个类添加新的方法.分类只能用 ...

  2. HTML中标签和元素的区别

    作为一个前端,相信大家最先接触应该都是HTML吧?在HTML中很多人可能都没有把什么叫标签,什么叫元素这个概念搞清楚,为了把这个大家不曾留意的易混淆的搞清楚,特作此一文彻底解决掉这个问题! 首先我们来 ...

  3. Android内存中的图片

    图片在内存中的大小 Android.graphics.Bitmap类里有一个内部类Bitmap.Config类,在Bitmap类里createBitmap(intwidth, int height, ...

  4. jboss7的服务器开启和关闭命令

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  5. Project Management - 1) Schedule Your Project

    1. 根据项目的理解,列出主要的里程碑. (初始甘特图) 2. 多使用即时贴,甘特图可以贴在墙上以供项目组成员提醒. 3. 切忌过早细化项目日程,这样会让老板或出资人以为项目中几乎没有风险, 他们会把 ...

  6. [React Fundamentals] Component Lifecycle - Mounting Basics

    React components have a lifecycle, and you are able to access specific phases of that lifecycle. Thi ...

  7. 今天升级了ADT到ADT 22.6.1,打包混淆的时候就出现了问题

    Proguard returned with error code 1. See console Error: Unable to access jarfile ..\lib\proguard.jar ...

  8. ios开发——笔记篇

    :开关 BOOL isopen = !isopen; //View @property (nonatomic, assign) BOOL open;//模型属性 self.group.open = ! ...

  9. android学习日记03--常用控件ListView

    常用控件 8.ListView 列表视图,比如游戏的排行榜.列表数据可以根据屏幕大小自适应 列表的显示需要三个元素: a.ListVeiw:用来展示列表的View. b.适配器:用来把数据映射到Lis ...

  10. Java HashMap 如何正确遍历并删除元素

    (一)HashMap的遍历 HashMap的遍历主要有两种方式: 第一种采用的是foreach模式,适用于不需要修改HashMap内元素的遍历,只需要获取元素的键/值的情况. HashMap<K ...