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

有一个数组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. cocos2d-x CCSpriteBatchNode

    转自:http://www.cnblogs.com/jiackyan/archive/2013/04/14/3019880.html 1.先说下渲染批次:这是游戏引擎中一个比较重要的优化指标,指的是一 ...

  2. 用CSS让网页背景图片居中的方法

    网页背景居中的方法有很多种的.这里介绍一些用CSS让背景图片居中的方法. 让背景图片居中的第一个方法是用像素设定,很多都用这种,但是也是最麻烦的: <div style="width: ...

  3. paip.mysql备份慢的解决

    paip.mysql备份慢的解决.txt 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.net/att ...

  4. [Python]linux自己定义Python脚本命令

    在window下写好的程序配置到Linux上,要实现随意文件夹下的命令调用. 因为初学Linux,这里从文件传输等最主要的方法入手,记录配置的过程中遇到的各种问题. 连接远端server 这里使用pu ...

  5. linux中的工具

    远程连接linux的工具: 命令行: SecureCRT   putty  XShell(商业环境付费) 图形界面:WinSCP SecureFX 远程连接window服务器工具: FileZilla ...

  6. Asp.Net 之 调用远程Web_Service

    一.添加web service引用 1.右键 Web 项目 → “添加服务引用”: 2.右键已有的 App_WebReferences 文件夹 → “添加服务引用”: 二.引用远程web servic ...

  7. View绘制详解,从LayoutInflater谈起

    自定义View算是Android开发中的重中之重了,很多小伙伴可能或多或少都玩过自定义View,对View的绘制流程也有一定的理解.那么现在我想通过几篇博客来详细介绍View的绘制流程,以便使我们更加 ...

  8. css实现响应式全屏背景

    利用css中 background-size:cover  填充整个viewport 注意: 一张背景图像素5000px*5000px在pc端 缩放都基本满足要求 不会出现模糊失真: 但是在移动端使用 ...

  9. ajax的一部分知识

    jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为String类型的参数,请求方式(p ...

  10. 利用iOS8新特性计算cell的实际高度

    在计算cell的实际高度是 我们一般是通过计算frame  拿到最底部一个控件的最大Y值从而的到cell 的高度  算来算去  比较麻烦 其实,iOS8已经提供了直接通过Cell高度自适应的方法了,根 ...