树状数组小结
2015-09-06 18:04
239 查看
树状数组基本概念
树状数组也是进行区间操作的常用数据结构。树状数组适用于单个元素经常修改,而且还反复求部分的区间和的情况.对于数组a,构造一个新的数组C,使得C[i] = a[i-2^k+1] + a[i-2^k+2] + ... + a[i];
(1) i >= 1;
(2) k为i在二进制表示下末尾的连续的0的个数,2^k = i&(-i),通常用lowbit(i)表示i对应的2^k,lowbit(i) = 2^k = i&(-i);
则数组C为数组a的树状数组。
数组数组的结构
树状数组对应的结构如下图所示:C[i] = a[i-lowbit(i)+1] + ... + a[i]
C[1] = a[1]
C[2] = a[1] + a[2]
C[3] = a[3]
C[4] = a[1] +a[2] + a[3] + a[4]
树状数组的操作
[b]一、求连续区间的和[/b]树状数组可以快速的求数组a的一个连续区间的和:
sum[k] = a[1] + a[2] + ... + a[k],则a[i] + a[i+1] + a[i+2] + ... +a[j] = sum[j] - sum[i-1]
如果用C数组来表示即为:
sum[k] = a[1] + a[2] + .. a[k] = C[N1] + C[N2] + ... +C[Nm]
其中 Nm = k, Ni-1 = Ni - lowbit(Ni), N1 >=1
//查询 int Query(int p, int n){ int sum = 0; while (p >= 1){ sum += gC[p]; p -= gLowBit[p]; } return sum; }
其中有log(n)个C元素,这就使得树状数组在连续区间求和时,可以达到log(n)的效率。
证明略
[b]二、单点更新[/b]
对原始数组a中的一个元素ai进行更新,树状有且仅有如下几项会被更新:C[N1], C[N2], ... C[Nm]
其中,N1 = i, Nk+1 = Nk + lowbit(Nk),且Nm <= N
//更新 void Update(int p, int n, bool add){ while (p <= n){ if (add){ gC[p] ++; } else{ gC[p] --; } p += gLowBit[p]; } }
树状数组和线段树
树状数组的应用范围窄,树状数组适用于单个元素经常修改,而且还反复求部分的区间和的情况。所有能用树状数组解决的问题,均可以用线段树解决;树状数组和线段树的时间复杂度均为O(nlogn),但是树状数组的常数小,效率略高;且树状数组的编程复杂度低。
相关文章推荐
- 回首来时的路!2014-2015总结
- iOS开发中ViewController切换动画的制作
- dom4j 创建xml
- 从一道面试题谈linux下fork的运行机制
- 分布式系统
- 部署项目之后,.jsp文件编译之后的.class文件放在了哪里?
- 使用CSS3配合IE滤镜实现渐变和投影的效果
- JVM学习笔记(三)------内存管理和垃圾回收
- 如何查看手机上安装的任意app的视图层次?
- hdu 3791 二叉搜索树
- BZOJ 1453 Wc2005 Dface双面棋盘 Link-Cut-Tree
- Unity Game Programming AI(5)A Star寻路算法
- 【转】java获取当前路径的几种方法
- Linux下的split 命令(将一个大文件根据行数平均分成若干个小文件)
- JAVA的StringBuffer类
- 【2015年总】——留不住的青春,散不去的梦
- 微信可以为整个业界提供很好的一个通信开放平台
- orcale 游标之依次插入 使用游标依次插入到数据中(支付清算)
- 使用Intellij14导入Android Library工程
- Unity性能优化原则(一)