博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树状数组
阅读量:5916 次
发布时间:2019-06-19

本文共 4071 字,大约阅读时间需要 13 分钟。

一、树状数组

树状数组是一个优美小巧的数据结构,在很多时候可以代替线段树。一句话概括就是,凡是树状数组可以解决的问题,线段树都可以解决,反过来线段树可以解决的问题,树状数组不一定能解决。

树状数组英文名称为Binary Index Tree,直译过来就是二进制索引树,我觉得二进制索引树更能说明其本质。树状数组的本质就是一种通过二进制位来维护一个序列前i和的数据结构。

 

1、更新元素

比如修改了a[3],则:

P1 = x = 3, L1 = 0;

P2 = p1+ 2(L1) = 3 + 1 = 4, L2 = 2;

P3 = p2 + 2(L2) = 4 + 4 = 8, L3 = 3;

....

2、子序列求和

比如求sum(6)

p1 = x = 6, L1 = 1; sum += c[6];

p2 = p1 - 2(L1) = 6 - 2 = 4; L2 = 2; sum += c[4];

p3 = p2 - 2(L2) = 4 - 4 = 0, return;

二、树状数组的维护

对于维护的序列A,定义C[i]=A[j+1]+...+A[i],其中ji的二进制表示中把最右边的1换成0的值。j的值可以通过lowbit求出,即i-lowbit(i)

lowbit(a)2^(a的二进制表示末尾0的个数)。可以用下面式子求出:

lowbit(a)=a&(a ^ (a-1))//或lowbit(a)=a&(~a+1)//或根据补码性质lowbit(a)=a&(-a)

 

 修改方式如下

void modify(int p,int delta)    {        while (p<=N)        {            C[p]+=delta;            p+=lowbit(p);        }    }

 

求前缀和如下

int sum(int p)    {        int rs=0;        while (p)        {            rs+=C[p];            p-=lowbit(p);        }        return rs;    }

 

三、示例代码

package ads;/** *  * @author loull * 下标index从1开始数 */public class BinaryIndexTree {    int[] c;    int n;    public BinaryIndexTree(int n) {        this.n = n;        c = new int[n+1];    }        int lowbit(int x) {        return x & (x ^ (x-1));    }    /**     * 更新一个元素,初始数组c都是0,所以可以用这个方法初始化c,这时候增加与更新是等价的     * @param p    更新第p个元素,索引从1开始     * @param d    增加的值,不是更新后的值     */    void update(int p, int d) {        while (p <= n) {            c[p] += d;            p += lowbit(p);        }    }        /**     * 计算从第一个元素到第p个元素的和     * @param p     * @return     */    int sum(int p) {        int ret = 0;        while (p > 0) {            ret += c[p];            p -= lowbit(p);        }        return ret;    }        public static void main(String[] args) {        int[] numbers = {1,2,3,4,5,6,7,8,9};        BinaryIndexTree bit = new BinaryIndexTree(numbers.length);        for (int i=0; i

 

 

四、C++模板

/****************************************                                      **    Template of Binary Indexed Tree   **                                      **           @author: Zyzsdy            **                                      ******************************************   Thanks: shu_mj                     **           ACM Template of Tokyo U    ****************************************/template 
struct binaryIndexTree { Type *data; int size_n; binaryIndexTree (int _size) : size_n (_size + 1) { data = new Type[size_n](); } ~binaryIndexTree() { delete [] data; } void add (int _lower, Type _delta) { int pos = _lower + 1; while (pos < size_n) { data[pos] += _delta; pos += pos & -pos; } } Type sum (int _lower, int _upper) { if (_lower > 0) { return sum (0, _upper) - sum (0, _lower); } else { Type result = 0; int pos = _upper; while (pos > 0) { result += data[pos]; pos -= pos & -pos; } return result; } }};typedef binaryIndexTree
BIT;

这份树状数组模板支持自动根据数据类型和数据量申请内存,单点更新和区间查询。就算不用模板,这份代码也很容易记忆。。

下面是HDU 1166,典型的树状数组题目,直接套上面的模板就可以解了。。因此不再放出完整代码,只贴上主函数,复制这两份代码再添上头文件即可运行。

int main(int agrc, char *agrv[]) {    int T;    scanf("%d",&T);for(int i=1;i<=T;i++){        printf("Case %d:n",i);        int n;        scanf("%d",&n);        BIT *ps=new BIT(n);        for(int j=0;j
updateDelta(j,p); } char buff[80]; while(true){ scanf("%s",buff); if(buff[0]=='E') break; int posi,shuj; switch(buff[0]){ case 'Q': int l,r; scanf("%d%d",&l,&r); printf("%dn",ps->sum(l-1,r)); break; case 'A': scanf("%d%d",&posi,&shuj); ps->updateDelta(posi-1,shuj); break; case 'S': scanf("%d%d",&posi,&shuj); ps->updateDelta(posi-1,-shuj); break; } } delete ps; }}

 

 

 

转载于:https://www.cnblogs.com/549294286/p/3783961.html

你可能感兴趣的文章
Oracle数据库常用函数使用--持续更新中
查看>>
js、jquery遍历对象
查看>>
Yarn中的几种状态机
查看>>
Java编程的逻辑 (87) - 类加载机制
查看>>
Codeforces Round #337 (Div. 2) 610C Harmony Analysis(脑洞)
查看>>
POJ 2007 Scrambled Polygon(简单极角排序)
查看>>
SQL Server中sys.syslogin中updatedate字段的浅析
查看>>
从头认识Spring-2.4 基于java的标准注解装配-@Inject(2)-通过set方法或者其它方法注入...
查看>>
JavaFX本地应用自己主动更新功能的实现FXLauncher
查看>>
JS实现关闭当前子窗口,刷新父窗口及调用父窗口的方法
查看>>
MapReduce源代码分析之JobSubmitter(一)
查看>>
/proc/modules分析
查看>>
POJ 2253 Frogger
查看>>
Sublime Text 格式化代码快捷键
查看>>
HTML5新特性:元素的classList属性与应用
查看>>
linux下yum命令出现Loaded plugins: fastestmirror
查看>>
String、StringBuffer、StringBuilder
查看>>
字节、字、位、比特,这四者之间的关系
查看>>
JVM 内存模型
查看>>
BZOJ离线版
查看>>