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

有一个数组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. 学习和理解C#中的事件

    注:本文系学习笔记. 上一篇文章记录了我对C#中委托的理解.委托实际上是一种类型.可以将一个或多个方法绑定到委托上面,调用委托时,一次执行委托上面绑定的方法.本文要讲述的事件实际上和委托有很深的“感情 ...

  2. 关系数据库 范式(NF: Normal Form) 说明

    关系数据库 范式(NF: Normal Form) 说明 数据库电话insertdelete存储oracle   目录(?)[+]   一.范式概述(NF:NormalForm) 数据库的设计范式是数 ...

  3. 数学之路(3)-机器学习(3)-机器学习算法-SVM[5]

    svm小结 1.超平面 两种颜色的点分别代表两个类别,红颜色的线表示一个可行的超平面.在进行分类的时候,我们将数据点  x 代入  f(x)  中,如果得到的结果小于 0 ,则赋予其类别 -1 ,如果 ...

  4. 别名的应用(New-Alias)

    New-Alias -name appcmd -value $env:windir\system32\inetsrv\appcmd.exe 这样就可以在当前PS环境下直接使用appcmd了

  5. 关于Excel Networkdays方法的实现

    最近一个程序要求excel输出的日期差为Networkdays. 在网上找了下,没有找到很好的具体实现方法. 要说明的是,微软的Microsoft.Office.Interop.Excel已经实现的N ...

  6. Java算法实例集合

    这里是princeton搜集的算法课程Java示例.包括超过了100 Java个算法程序源码.Javadoc和测试数据.点击这里查看.

  7. Oracle 11g系统自己主动收集统计信息的一些知识

    在11g之前,当表的数据量改动超过总数据量的10%,就会晚上自己主动收集统计信息.怎样推断10%.之前的帖子有研究过:oracle自己主动统计信息的收集原理及实验.这个STALE_PERCENT=10 ...

  8. careercup-中等难度 17.6

    17.6 给定一个整数数组,编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的.注意:n越小越好,也就是说,找出符合条件的最短序列. 解法: 开始解题之前,让我们先确认一下 ...

  9. PAT 1010

    1010. Radix (25) Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 11 ...

  10. JAVA获取CLASSPATH路径--转

    ClassLoader提供了两个方法用于从装载的类路径中取得资源: public URL getResource(String name);         public InputStream ge ...