树状数组(搬运自维基百科)
2016-04-10 18:46
302 查看
树状数组(Fenwick_tree),最早由Peter M. Fenwick于1994年以A New Data Structure for Cumulative Frequency Tables为题发表在SOFTWARE PRACTICE AND EXPERIENCE。其初衷是解决数据压缩里的累积频率(Cumulative Frequency)的计算问题,现多用于高效计算数列的前缀和。它可以以
![](https://upload.wikimedia.org/math/0/c/a/0ca47d9a481af371d1210a620c1945db.png)
的时间得到
![](https://upload.wikimedia.org/math/5/8/4/584c01c46478dffe78795b5737598683.png)
,并同样以
![](https://upload.wikimedia.org/math/0/c/a/0ca47d9a481af371d1210a620c1945db.png)
对某项加一个常数。
2)修改;
3)求和;
lowbit求法:
![](https://upload.wikimedia.org/math/7/f/c/7fc56270e7a70fa81a5935b72eacbe29.png)
的前缀和,则:
![](https://upload.wikimedia.org/math/d/a/7/da79c608cb628c39022efcad1025dbab.png)
具体能用以下方式实现:
![](https://upload.wikimedia.org/math/8/a/6/8a6b5ab46e06fa60418f7c34e624b076.png)
的值增加delta,
那么,需要将
![](https://upload.wikimedia.org/math/3/a/9/3a98a50f7623067e3baeac2a6c0ddfdf.png)
覆盖的区间包含
![](https://upload.wikimedia.org/math/8/a/6/8a6b5ab46e06fa60418f7c34e624b076.png)
的值都加上K.
这个过程可以写成递归,或者普通的循环.
需要计算的次数与数据规模N的二进制位数有关,即这部分的时间复杂度是O(LogN)
![](https://upload.wikimedia.org/math/9/a/c/9accf143504f21bb899d21d647227f66.png)
的值.
首先,将ans初始化为0,将i计为k.
将ans的值加上BIT[P]
将i的值减去lowbit(i)
重复步骤2~3,直到i的值变为0
![](https://upload.wikimedia.org/math/0/c/a/0ca47d9a481af371d1210a620c1945db.png)
的时间得到
![](https://upload.wikimedia.org/math/5/8/4/584c01c46478dffe78795b5737598683.png)
,并同样以
![](https://upload.wikimedia.org/math/0/c/a/0ca47d9a481af371d1210a620c1945db.png)
对某项加一个常数。
基本操作:
1)新建;2)修改;
3)求和;
lowbit求法:
int lowbit(int x) { return x&(-x); }
新建:
定义一个数组 BIT,用以维护![](https://upload.wikimedia.org/math/7/f/c/7fc56270e7a70fa81a5935b72eacbe29.png)
的前缀和,则:
![](https://upload.wikimedia.org/math/d/a/7/da79c608cb628c39022efcad1025dbab.png)
具体能用以下方式实现:
void build() { for (int i=1;i<=MAX_N;i++) { BIT[i]=A[i]; for (int j=i-1; j>i-lowbit(i); j--) BIT[i]+=A[j]; } }
修改:
假设现在要将![](https://upload.wikimedia.org/math/8/a/6/8a6b5ab46e06fa60418f7c34e624b076.png)
的值增加delta,
那么,需要将
![](https://upload.wikimedia.org/math/3/a/9/3a98a50f7623067e3baeac2a6c0ddfdf.png)
覆盖的区间包含
![](https://upload.wikimedia.org/math/8/a/6/8a6b5ab46e06fa60418f7c34e624b076.png)
的值都加上K.
这个过程可以写成递归,或者普通的循环.
需要计算的次数与数据规模N的二进制位数有关,即这部分的时间复杂度是O(LogN)
void edit(int i, int delta) { for (int j = i; j <= MAX_N; j += lowbit(j)) BIT[j] += delta; }
求和:
假设我们需要计算![](https://upload.wikimedia.org/math/9/a/c/9accf143504f21bb899d21d647227f66.png)
的值.
首先,将ans初始化为0,将i计为k.
将ans的值加上BIT[P]
将i的值减去lowbit(i)
重复步骤2~3,直到i的值变为0
int sum (int k) { int ans = 0; for (int i = k; i > 0; i -= lowbit(i)) ans += BIT[i]; return ans; }
相关文章推荐
- 作业四
- Nutch
- FZU 2150 Fire Game
- DG
- PhoneGap极光推送插件使用
- 继承和多态的那些事
- poj 1419
- (水)POJ-1321 棋盘问题
- git入门
- android 读取Bitmap的几种方式
- microsoft office professional plus2007在安装过程中出错
- hadoop修改block size,并上传文件
- ggplot2 legend图例的修改
- 学习进度表第六周
- [Lintcode]Rotate String 两步翻转法
- C++: string的大小写转换
- 1.OSI(开放系统互连(Open System Interconnection))模型
- 团队视频
- HTML5 之 CSS简单使用(一)
- Unity3d--随机数Random.rotation