【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)
来源:互联网 发布:javac编译多个java文件 编辑:程序博客网 时间:2024/06/05 17:31
在网上找到一篇非常不错的树状数组的博客,拿来转载,原文地址。
树状数组
最新看了一下区间的查询与修改的知识,最主要看到的是树状数组(BIT),以前感觉好高大上的东西,其实也不过就这么简单而已。
我们有一个动态连续和查询问题:给定一个n个元素的数组
1:
2:
第一种思路就是循环累加,这样每次的时间复杂度都是
在讲BIT之前,我们来先了解一个函数:对于任意正整数x,我们定义lowbit(x)为x的二进制中最右边的1所对应的值,比如,5的二进制是101,那么lowbit(5)= 1;4的二进制是100,那么lowbit(4) = 4;在程序实现中,lowbit代码如下
(此处对原文中的代码有修改)
int lowbit (int x){ return x & (-x);}
这里用到的是按位运算,请读者自己去查阅关于这点的资料。但为什么呢?计算机里面的整数采用补码表示,-x实际上是x在二进制中按位取反,末位+1后的结果,二者按位取“与”之后,前面全部变成0,之后的lowbit保持不变;
接下来给大家附上一张BIT 的图,其实也不是很难懂,但是我想要的图我找不到了,所以就附一个别的图吧,希望大家能尽量去看,在下面我会给大家解释其中C数组的含义
其中我们可以看到C[i]是有分层问题的,那么到底是怎么分层的呢,实际上就是根据lowbit(i)的值来分的层。
在这里我们可以看到BIT是有连线的,但实际上这些连线在计算机中并不存在,只是为了读者好理解才加上的。其实BIT本身就是一棵二叉树(具体请翻阅前面BIT的定义),那么这棵树上面就会有父亲节点和左右儿子节点(实际上在图中没有看到右孩子与父亲节点的连线,我们可以想象一下)
关于在BIT上节点的父子关系,我们是这样定义的:
对于节点i,如果它是左子节点,那么它的父节点的编号为i+lowbit(i);如果它是右子节点,那么它的父节点编号为i+lowbit(i)。大家可以自己证明一下这个东西。搞清楚BIT 结构之后,我们来讲一下这个C数组是干嘛的。
C数组实际上只是个辅助数组,其中C[i]=A[i-lowbit(i)+1]+A[i-lowbit(i)+2]+……+A[i];可以看出,C数组就是用来辅助计算前缀和S[i]的;
那么我们有了C数组之后,如何计算S[i]呢?顺着i节点往左走,边走边往上爬(这里请注意,不一定沿着BIT中的边爬),把沿途的C[i]累加起来就好了(请读者注意,这里沿途经过的C[i]毫无遗漏和重复的走完了A[i]),那么下面我给大家附上这个求前缀和操作的代码(这里我只会给出核心代码,因为全部代码给出真的就是没必要):
int Query(int x){ int ret = 0; while(x > 0){ ret += C[x]; x-=lowbit(x); } return ret;}
下面来讲一下修改问题,因为BIT是一棵树,而且根据前面的C[i]的定义,我们可以知道,当某个A[i]改变时,有一些C[i]也会改变,那么需要更改那些C数组中的元素呢?从C[i]开始往右走,边走边“往上爬”(同上,不一定要沿着图中的边爬),沿途修改经过所有节点对应的C[i]值即可。下面附上更改元素的代码(同样只给出核心代码):
void add(int x,int d){ while(x <= n){ C[x] += d; x += lowbit(x); }}
这两个操作的时间复杂度都是
BIT的推广:二位BIT:
一维BIT很容易推广到二维,二维BIT如下所示:
C[x][y] = sum(A[i][j]);
二维BIT的应用:
一个由数字构成的大矩阵,支持以下操作:
1.给矩阵中某个元素加上一个整数d(正负都可以);
2.查询某个子矩阵中所有数字的和
并且对每个查询操作输出结果.
转载于2015年8月29日。
- 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)
- 区间信息的维护与查询1(树状数组)
- 区间信息的查询与维护(一)树状树组
- 区间信息的维护和查询系列算法-树状数组
- LA 4329 - Ping pong 树状数组(Fenwick树)
- LA 5902 - Movie collection 树状数组(Fenwick树)
- 二叉索引树——树状数组
- 二叉索引树(树状数组)
- 树状数组(二叉索引树)
- 二叉索引树(树状数组)
- 二叉索引树(树状数组)
- 二叉索引树(树状数组)
- BIT二叉索引树(树状数组)
- 二叉索引树(树状数组)
- 树状数组(二叉索引树)
- UVa12086 - Potentiometers(树状数组即Fenwick树)
- 区间信息的维护与查询
- poj3468 树状数组解法(树状数组维护区间更新)
- jquery选择器用法
- android平台led开发之内核硬件驱动层
- linux运行、关闭、查看后台任务
- PCIE协议解析 synopsys IP Register配置空间 读书笔记(8)
- ZOJ 3557-How Many Sets II(Lucas定理+插板法求组合数)
- 【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)
- Delphi 调用极光推送服务端HTTP API实例
- Appium的python_client的安装过程解析。
- Word查找替换栏代码和通配符一览表
- hdu 1599 find the mincost route
- oracle11g 安装步骤详解
- solaris下安装pkg.bz2文件
- zend studio中建立svn项目
- geotools 实例