特点

代码短、常数很小


应用及时间复杂度

  1. 区间查询:求前缀和
  2. 单点修改:给某个位置上的数加上一个数(同时能以非常小的代价维护前缀和)

时间复杂度:O(logn)O(logn)O(logn)


与一般前缀和算法的对比

算法 修改某个点 查询前缀和 平均时间复杂度(假定两种操作各占50%50\%50%)
一般前缀和 O(n)O(n)O(n) O(1)O(1)O(1) O(n)O(n)O(n)
树状数组 O(logn)O(logn)O(logn) O(logn)O(logn)O(logn) O(logn)O(logn)O(logn)

可以看出在修改和查询操作占比差不多时,树状数组的效率更高

那么什么时候用树状数组,什么时候用一般前缀和算法呢?
这就要明白这两个算法的本质区别:
一般前缀和算法是离线算法,它不支持动态的改变单个元素的值,或者说改变单个元素值后,重新维护前缀和所花费的代价很大。
树状数组是在线算法,支持动态改变单个元素的值,以很小的代价动态维护前缀和。
所以当仅仅需要用到前缀和,不涉及动态的改变单个元素的值时,首选一般前缀和算法,否则就用树状数组


树状数组原理

树状数组图例(下标从111开始

假设原序列为aaa,树状数组序列为ccc,那么是怎么由原序列得到树状数组序列的呢?(可以把ccc理解为aaa的前缀和序列,只是前缀和关系不像一般前缀和那样简单、线性)

  1. 首先,将一维的树状数组序列ccc看成多层的序列,c[i]c[i]c[i]属于第几层,取决于iii的二进制表示中最后一个111后面有几个000,有几个000就在第几层,显而易见,当iii为奇数时,c[i]c[i]c[i]是在第000层的
    因为lowbit(x)=2klowbit(x)=2^{k}lowbit(x)=2k,kkk表示x的二进制表示后面有多少个0
    (lowbit(n)lowbit(n)lowbit(n)求得n的二进制表示中最后一个1以及往后的0)
    可以得到关系:
    c[x]=a(x−lowbit(x),x]c[x]=a(x-lowbit(x),x]c[x]=a(x−lowbit(x),x]
    此关系描述了序列ccc中每个元素是哪一段序列aaa中元素的和
  2. 如何通过树状数组求前缀和?
    由上面公式知道,想要求序列aaa中111到xxx的和,则应该是:

    ∑i=1xai=c[x]+c[x−lowbit(x)]+......\sum_{i=1}^{x}a_i=c[x]+c[x-lowbit(x)]+......∑i=1x​ai​=c[x]+c[x−lowbit(x)]+......
    因而可得代码:
int res=0;
for(int i=x;i>0;i-=lowbit(x)) res+=c[i];
return res;
  1. 如何通过树状数组进行单点修改?
    这里我们给出一个结论:一个结点a[i]a[i]a[i]或c[i]c[i]c[i]的父结点为c[i+lowbit(i)]c[i+lowbit(i)]c[i+lowbit(i)]
    所以当我们改变a[i]a[i]a[i]的值时,依次递归向上更新父结点的值即可
    代码:
a[x]+=v;
for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v;

我们发现这里是给某个数加上一个数vvv,而不是把某个数变成vvv,如果想实现这样的效果,该怎么做呢?
我们可以把加的数vvv灵活的调整为v−xv-xv−x(假设原来的数为xxx),加上v−xv-xv−x之后原来的数xxx就变成vvv了,从而实现了让一个数变成一个给定的数的效果。
获得原来的数的方式:

  • 树状数组前缀和相减:c[x]−c[x−1]c[x]-c[x-1]c[x]−c[x−1]
  • 开一个数组存原数组

树状数组只能给一个数加上一个数,而不能把一个数变成一个数,要实现这样的操作,作上面的变换即可


初始化树状数组

可以假设原序列aaa为全0,依次通过“单点修改”操作把每个数加进去,最后就可以形成树状数组了。


例题:AcWing 1264. 动态求连续区间和

#include<iostream>
using namespace std;
const int N=100010;
int a[N],c[N];
int n,m;
int k,x,y;
int lowbit(int x)
{return x&(-x);
}
void add(int x,int v)
{for(int i=x;i<=n;i+=lowbit(i)) c[i]+=v;
}
int query(int x)
{int res=0;for(int i=x;i>0;i-=lowbit(i)) res+=c[i];return res;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) add(i,a[i]);   //初始化while(m--){scanf("%d%d%d",&k,&x,&y);if(k==0) printf("%d\n",query(y)-query(x-1));   //前缀和思想else add(x,y); }return 0;
}

树状数组 思路以及性能分析相关推荐

  1. HDU 4638 Group 树状数组 + 思路

    实际上就是问这个区间编号连续的段的个数,假如一个编号连续的段有(a+b)个人,我把他们分在同一组能得到的分值为(a+b)^2,而把他们分成人数为a和b的两组的话,得到的分值就是a^2+b^2,显然(a ...

  2. 树状数组(详细分析+应用),看不懂打死我!

    树状数组介绍 在学习一个算法之前一定要清楚它能干嘛,能解决什么样的问题,对你解题是否有帮助,然后才去学习它! 那么接下来看如下几个问题 什么是树状数组 顾名思义就是一个结构为树形结构的数组,于二叉树的 ...

  3. 如此好的树状数组学习资料

    树状数组学习系列1 之 初步分析--czyuan原创 其实学树状数组说白了就是看那张图,那张树状数组和一般数组的关系的,看懂了基本就没问题了,推荐下面这个教程:http://www.topcoder. ...

  4. AcWing 蓝桥杯AB组辅导课 05、树状数组与线段树

    文章目录 前言 一.树状数组 1.1.树状数组知识点 1.2.树状数组代码模板 模板题:AcWing 1264. 动态求连续区间和 例题 例题1.AcWing 1265. 数星星[中等,信息学奥赛一本 ...

  5. [算法模板]树状数组

    [算法模板]树状数组 思路 图片转自:yhf_2015--彻底理解树状数组 使用这个图片就能很快的理解树状数组. 我们可以先根据图片来分解一个十进制数成二次幂. example: \(15=2^0+1 ...

  6. E. String Reversal (树状数组)

    E. String Reversal (树状数组) 思路:树状数组 考虑每个位置的贡献,从最后一个字符开始计算. 显然对于相同的字符选取靠前的位置的贡献更小. 所以用队列维护相同字母的位置. 从后往前 ...

  7. 1010 Lehmer Code (35 分)(思路+详解+树状数组的学习+逆序对+map+vector) 超级详细 Come baby!!!

    一:题目 According to Wikipedia: "In mathematics and in particular in combinatorics, the Lehmer cod ...

  8. poj 2352 Stars 线段树(先建后查/边建边查)/树状数组三种方法思路详解,带你深入了解线段树难度⭐⭐⭐★

    poj 2352 Stars 目录 poj 2352 Stars 1.树状数组 2.线段树,先建树后查找 3.线段树,边建树边查找 Description Astronomers often exam ...

  9. HDU 4358 树状数组+思路

    http://acm.hdu.edu.cn/showproblem.php?pid=4358 如图所示,当k==3时,如果我们扫描到红线所在的位置. 则符合条件的区间就是从红线到两条紫线所包含的区间( ...

最新文章

  1. 你知道Java文件拷贝有几种方式么?
  2. C++ 构造函数的初始化列表
  3. linux 如何运行r脚本,Linux系统下如何debug R脚本
  4. 真实临床“生态”下实效性研究的挑战和意义
  5. 希尔排序-Java二
  6. windows环境下 curl 安装和使用
  7. c语言判定三角形方法,c语言判定三角形的各种类型——请大家指点
  8. AGC005D - ~K Perm Counting(组合数学,背包,dp)
  9. CSP2021NOIP2021游记
  10. java comparator_【面试题】Java必考面试题全集(15)
  11. 一个程序员的逗逼瞬间(二)
  12. 记录下最近使用到的sql语句
  13. 【转】Pro Android学习笔记(八):了解Content Provider(下中)
  14. 15 —— npm —— package.json 与 package-lock.json 的作用
  15. 个人Blog小程序开发完毕
  16. EXT Column Tree 的应用
  17. java程序如何安装到手机上_java怎么安装到手机?手机安装java的教程
  18. 联想计算机 经常蓝屏怎么办,一分钟看懂电脑蓝屏(内附解决方案)
  19. iframe背景色透明
  20. 直连路由、主机路由以及选择顺序

热门文章

  1. ubuntu绝对路径和相对路径自动补全
  2. 数据结构(c++)学习笔记--排序
  3. .NET 实现RSA加密解密 C#
  4. 《一无所获满载而归》——孙溟㠭(展)书法绘画篆刻
  5. 用笔记本煎蛋,伊莱克斯推出笔记本电磁炉
  6. 小马哥----高仿小米note主板H79 型号 刷机拆机主板图与开机界面图 新版机型 警惕
  7. ActivityNet Kinetics夺冠 | PaddlePaddle视频联合时空建模方法开源
  8. 第六次作业--结对编程
  9. mac os启动mysql
  10. 什么是ClickHouse?