树状数组

来源:互联网 发布:手机淘宝怎么代购 编辑:程序博客网 时间:2024/06/08 01:33

树状数组(binary indexed tree)
概念:是一种数组结构
目的:高效地获取数组中连续n个数的和。
应用 :序列中的元素可不断地被修改,要快速地获取某区间和(单点更新,区间求和)
前注 :如果每次要修改的不是单个元素,而是一个区间,那不应当用树状数组(效率过低)

操作:
1.修改元素(增减值) –> O(logn)
2.求区间和 –> O(logn)

实现:
给定序列(数列)A,我们设一个数组C满足

C[i] = A[i–2^k+ 1] + … + A[i]        (K为 i在二进制下末尾0的个数, i >= 1)  --> 给定 i,则有 2^k = i&(i^(i-1)) = i&(-i)

图示:
这里写图片描述

修改元素:
————–>若要修改A[i]的值时,只需从C[i]往根节点一路上溯,调整这条路上的所有C[]。
区间求和:
————–>求数列的前n项和,只需找到n以前的所有最大子树,把其根节点的C[]值加起来。(子树的数目是n在二进制时1的个数)

int lowbit(int n){//求 2^k , k 为n在二进制下末尾0的个数    return n & (-n); // == n & (n^(n-1));}int Sum(int End)        {//求前n项和    int ans = 0;    while(End > 0)    {        ans += treeC[End];        End -= lowbit(End);    }    return ans;}void Plus(int pos,int num,int len) {//增加某元素的值    while( pos <= len )    {        treeC[pos] += num;        pos += lowbit(pos);    }}

例题 http://acm.hdu.edu.cn/showproblem.php?pid=1166


高级应用 : 区间更新 单点查找

操作:
1.区间更新
例如 :
在 区间[ Begin,End] 加 Add

则Plus(Begin,Add)   Plus(End+1,-Add)实现了更新区间[ Begin,End] 的值而不改变其他值

2.单点查找

Sum(i) 即为 A[i] 的值

例题 http://acm.hdu.edu.cn/showproblem.php?pid=1556


推广 : 二维树状数组
用途 :
一个由数字构成的大矩阵,能进行
操作
1) 修改矩阵元素(增减值)
2) 求子矩阵的和

求和有
有 C[x][y] = sum{ A[i][j] , x - lowbit[x] +1 <=i <= x , y-lowbit[y]+1 <= j <=y }

0 0
原创粉丝点击