在网上找到一篇非常不错的树状数组的博客,拿来转载,原文地址

树状数组

最新看了一下区间的查询与修改的知识,最主要看到的是树状数组(BIT),以前感觉好高大上的东西,其实也不过就这么简单而已。

我们有一个动态连续和查询问题:给定一个n个元素的数组A1,A2,A3,…An,你的任务是设计一个数据结构,使得其支持以下两个操作:

1:Add(x,d)操作:让Ax增加d;

2:Query(L,R)操作:计算AL+AL+1+⋯+AR。

第一种思路就是循环累加,这样每次的时间复杂度都是Θ(n)级别的。这样在数据很大的情况之下,是一定会效率很低的,所以我们引进了二叉索引树(也就是树状数组)这种比较高级的数据结构,说它高级,也高不到那里去,也就是比原先我们学过的数据结构难一些就是了,这种数据结构在NOI中是经常使用的,但是NOIP一般不考,我也是一个NOIPer,水平也是达不到NOI的,只是我感觉这个东西挺好玩,也挺实用的,所以就学了学,发一篇博客。

在讲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);
}
}

这两个操作的时间复杂度都是Θ(log2n)预处理方法是将A和C数组清空,再执行n次add操作,总时间复杂度为Θ(nlog2n);

BIT的推广:二位BIT:

一维BIT很容易推广到二维,二维BIT如下所示:

C[x][y] = sum(A[i][j]);

二维BIT的应用:

一个由数字构成的大矩阵,支持以下操作:

1.给矩阵中某个元素加上一个整数d(正负都可以);

2.查询某个子矩阵中所有数字的和

并且对每个查询操作输出结果.

转载于2015年8月29日。

【转载】区间信息的维护与查询(一)——二叉索引树(Fenwick树、树状数组)的更多相关文章

  1. 树状数组(二叉索引树 BIT Fenwick树) *【一维基础模板】(查询区间和+修改更新)

    刘汝佳:<训练指南>Page(194) #include <stdio.h> #include <string.h> #include <stdlib.h&g ...

  2. 二叉搜索树TREE(线段树,区间DP)

    前言 线段树+区间DP题,线段树却不是优化DP的,是不是很意外? 题面 二叉搜索树是一种二叉树,每个节点都有一个权值,并且一个点的权值比其左子树里的点权值都大,比起右子树里的点权值都小. 一种朴素的向 ...

  3. hdu 1166 敌兵布阵——(区间和)树状数组/线段树

    pid=1166">here:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Input 第一行一个整数T.表示有T组数据. 每组数据第一 ...

  4. 牛客练习赛52 B题【树状数组维护区间和{查询区间和,如果区间元素重复出现则计数一次}】补题ing

    [题目] 查询区间和,如果区间元素重复出现则计数一次. 链接:https://ac.nowcoder.com/acm/contest/1084/B [题解] 将询问按r排序,维护每个数最后出现的位置, ...

  5. BZOJ 1018: [SHOI2008]堵塞的交通traffic [线段树 区间信息]

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3064  Solved: 1027[Submi ...

  6. nyoj 123 士兵杀敌(四) 树状数组【单点查询+区间修改】

    士兵杀敌(四) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5   描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战 ...

  7. 线段树 区间开方区间求和 & 区间赋值、加、查询

    本文同步发表于 https://www.zybuluo.com/Gary-Ying/note/1288518 线段树的小应用 -- 维护区间开方区间求和 题目传送门 约定: sum(i,j) 表示区间 ...

  8. Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)

    这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...

  9. Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

    一看就知道 可以LCA判断做 也可以树链剖分拿头暴力 然而快速读入和线段树维护区间会T70 于是只能LCA? 线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组 这个题 ...

随机推荐

  1. Redis 安装为Window服务

    参考: http://www.cnblogs.com/zhoub/p/3841222.html 关键命令 redis-server.exe –service-install conf/redis.co ...

  2. BZOJ4421 : [Cerc2015] Digit Division

    如果两个相邻的串可行,那么它们合并后一定可行,所以求出所有可行的串的个数$t$,则$ans=2^{t-1}$. 注意特判整个串不可行的情况,这个时候答案为0. #include<cstdio&g ...

  3. jq prepend() 方法在被选元素的开头(仍位于内部)插入指定内容。 提示:prepend() 和 prependTo() 方法作用相同。差异在于语法:内容和选择器的位置,以及 prependTo() 无法使用函数来插入内容。

    <html><head><script type="text/javascript" src="/jquery/jquery.js" ...

  4. 让 Web 站点崩溃最常见的七大原因

    磁盘已满 导致系统无法正常运行的最可能的原因是磁盘已满.一个好的网络管理员会密切关注磁盘的使用情况,隔一定的时间,就需要将磁盘上的一些负载转存到备份存储介质中(例如磁带).   日志文件会很快用光所有 ...

  5. CSS z-index 属性的使用方法和层级树的概念

    之前有一篇文章提到过z-index,我们知道只有在元素设置了position部位static时才生效,而且z-index也跟父元素有关系,今天就在ie7遇到类似问题,在网上查了一些资料,发现一篇好文章 ...

  6. 【HDU】1847 Good Luck in CET-4 Everybody!

    http://acm.hdu.edu.cn/showproblem.php?pid=1847 题意:同nim..不过只有一堆..每次取2的幂次..即1.2.4....等,n<=1000 #inc ...

  7. 51nod算法马拉松12

    A 第K大区间 不妨考虑二分答案x,则问题转化成计算有多少个区间满足众数出现的次数>=x. 那么这个问题我们使用滑动窗口,枚举右端点,则左端点肯定单调递增,然后维护一个简单的数组就能资瓷添加元素 ...

  8. This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.

    一,经历 <1> 使用SDWebImage下载 成功图片后,将图片设置给 self.imageView.image,提示如题所示的错误提示. <2>第一反应就是慢慢注释掉代码进 ...

  9. spring源码学习之路---环境搭建(一)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近已经开始了spring源 ...

  10. JQuery+Ajax制作省市联动

    $(document).ready(function () { $("#Province").append("<option value=''>" ...