树状数组粗略讲解
来源:互联网 发布:薛之谦话题精华知乎 编辑:程序博客网 时间:2024/03/29 15:24
优势:对于普通数组,其修改的时间复杂度位O(1),而求数组中某一段的数值和的时间复杂度为O(n),因此对于n的值过大的情况,普通数组的时间复杂度我们是接受不了的。在此,我们引入了树状数组的数据结构,它能在O(logn)内对数组的值进行修改和查询某一段数值的和。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。这种数据结构(算法)并没有C++和Java的库支持,需要自己手动实现。在竞赛中被广泛的使用。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。但相比较而言,树状数组效率要高很多。
下面就开始举例,以a数组来存储输入的数,c数组来表示A数组形成的树状数组。
我们来观察这个图
c1=a1
c2=c1+a2=a1+a2
c3=a3
c4=c2+c3+a4=a1+a2+a3+a4
c5=a5
c6=c5+a6=a5+a6
c7=a7
c8=c4+c6+c7+a8=a1+a2+a3+a4+a5+a6+a7+a8
c9=a9
这里有个规律
设节点编号为i,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ai
所以很明显:Ci= A(i – 2^k + 1) + … + Ai
而这个2^k有种快速求法
int lowbit(int x){ return x&(x^(x–1)); }
利用机器的补码原理也可以写成这样:
int lowbit(int x){ return x&(-x); //我们做题大部分也这么写的}
下面我们可以随便举几组数据来判断下它的正确性
比如i=6 它的二进制表示为110 所以k=1(因为110末尾只有1个0) 2^k=2 6&(-6)=2
C6=A5+A6
又比如i=7 它的二进制表示为111 所以k=0(末尾没有0) 2^k=1 7&(-7)=1
C7=A7
又比如i=8 二进制表示为1000 所以k=3 2^k=8
8&(-8)=8
C8=A1+A2+A3+A4+A5+A6+A7+A8
void add(int i,int x)//添加元素构成树状数组 i为位置 x为元素{ while(i<=n) { c[i]+=x; i+=lowbit(i); }}
当取一段数的和的时候
int sum(int i)//i为位置 如果你想取u,v之间的和 即就是sum(u)-sum(v-1){ int k=0; while(i>0) { k+=c[i]; i-=lowbit(i); } return k;}
所以树状数组的模板代码如下:
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <map>#include <cmath>#include <queue>#include <string>#include <vector>#include <set>using namespace std;#define sc(x) scanf("%d",&x)#define FOR(i,n,o) for(int i=o;i<=n;i++)#define pr(x) printf("%d\n",x)#define lcr(a,b) memset(a,b,sizeof(a))const int maxn=10e2+10;int n,m;int c[maxn];int lowbit(int x){ return x&(-x);}void add(int i,int x){ while(i<=n) { c[i]+=x; i+=lowbit(i); }}int sum(int i){ int k=0; while(i>0) { k+=c[i]; i-=lowbit(i); } return k;}int main(){ while(~sc(n)) { int a; lcr(c,0); FOR(i,n,1) { sc(a); add(i,a); } sc(m); int u,v; int ans=0; while(m--) { scanf("%d%d",&u,&v); ans=sum(v)-sum(u-1); pr(ans);//v u之间的和 } } return 0;}
END!!!!!!!!!!!!!!!!!!!!!!!!!!
1 0
- 树状数组粗略讲解
- 树状数组讲解
- 树状数组讲解
- 数据结构-树状数组讲解
- 知识点:树状数组讲解
- 树状数组经典讲解
- 8.26树状数组讲解
- 树状数组讲解
- 树状数组 讲解(转载)
- 树状数组(讲解+模版)
- 集训8.21树状数组讲解
- request_mem_region粗略讲解
- 快速排序讲解(粗略)
- kmp算法粗略讲解
- 浅谈树状数组(伪讲解)
- 树状数组 讲解和题目集
- [BZOJ 2124] 等差子序列 Hash+树状数组(附粗略证明)
- MYSQL的索引粗略讲解
- BufferedImage是什么意思?
- 动态实现的方式
- 从外置sdcard读取数据
- BZOJ4066: 简单题
- 一张图解释常用开源许可证的区别
- 树状数组粗略讲解
- 深入浅出 RPC - 深入篇
- 流程控制
- elasticsearch2.3.5集群配置
- 介绍Collection框架的结构;Collection 和 Collections的区别
- 【poj1079】 Triangle
- iOS开发 - 第05篇 - 项目 - 08 - 发微博
- 截取http请求(burpsuit工具,fiddler,winsock expert)
- 求相等和