【数据结构】——树状数组的几种模型
来源:互联网 发布:传奇app源码 编辑:程序博客网 时间:2024/05/19 22:03
树状数组
基本定义:树状数组是利用二分的思想使得查询和修改的复杂度都为log(n)的数据结构,主要用于查询数组前缀和、区间和并且经常更改数据。
数据结构思想:如上图,2的k次方的位置存放1一直到
基本操作:而要实现这一点,就要求一个二进制数的最低位1,这个可以用lowbit操作实现:
一个二进制数x对其进行x&(-x)的操作,就可以保留其最低位的1,而讲其他全部位全清零
所以一个数加上自己的lowbit,就到了上一级包含自己的区间,例如110(6)加上10变成了1000(8),因为1000对应的0~1000
同样,减去自己的lowbit就相当于去尾。
模型1:改点求点求段
//设M为最大数的上限,treeray存树状数组void add(int k,int num)//像某个位置添加的操作{ while(k<=M)//防止上界溢出 { treeray[k]+=num; k+=k&(-k);//不断加上lowbit来向上更新包含自己的区间 } return;}int read(int k)//读取以某个位置为终点的前缀和{ int sum=0; while(k)//一定要注意树状数组不能储存0这个位置 { sum+=treeray[k]; k-=k&(-k);//不断减lowbit来加上前面区间的和 } return sum;}
模型2:改段求点
当需要改段求点时,利用树状数组方便求前缀和的特性,我们采用记录变化量的技巧,就可以使得一个数的前缀和变成他之前所有的变化量,便可得到这个数本身。
在树状数组中,每个数初始化为0,然后每个位置记录它与左边的差值,如图所示:
//add与read函数同上//当在a与b间全部加上c时add(a,c);add(b+1,c);//当要得到k的值时read(k);
模型3:改段求段
当需要改段求段时,与前一种类型的区别是,需要求某一点“真正的”前缀和。考虑前一种方法,只知道该点本身与前面所有变化量的总和,却不知道这些变化是从哪里开始的,无法方便地求出前缀和。我们先假设这个点之前所有数都与这个点相等,这样必然会多出前面的一些变化值变化长度这么多,那么我们再用一个树状数组,其中在每一个变化点记录变化值变化长度,那么最终算某个点的和,只需要再减去这个树状数组的在该点的值,如图所示:
int A[],B[]; //两个树状数组void tadd(int a[],int x,int c){ while(x<=N) { a[x]+=c; x+=lowbit(x); } return;}int tread(int a[],int x){ int sum=0; while(x>0) { sum+=a[x]; x-=lowbit(x); } return sum;}void update(int a,int b,int c){ tadd(A,a,c); tadd(A,b+1,-c); tadd(B,a,c*(a-1)); //叠加前缀变化量 tadd(B,b+1,-c*b); return;}int querry(int a,int b){ int sum1=tread(A,a-1)*(a-1)-tread(B,a-1); int sum2=tread(A,b)*b-tread(B,b); return sum2-sum1;}
模型4:多维树状数组(以二维为例)
多维树状数组只需把多维的每一维度分别当作一维树状数组即可,那么N维的某一点的前缀和,其实就是,各个维度的前缀和分别映射到其他维度的前缀和
所以这里给出二维树状数组的代码实现,具体可以见下面的例题POJ1195:
void tadd(int i,int j,int c){ for(int x=i;x<=N;x+=lowbit(x)) for(int y=j;y<=N;y+=lowbit(y))//一定要注意这里不能再直接用传入的形参j了,因为每次循环都要使之成为刚传入的值 base[x][y]+=c; return;}int tread(int i,int j){ int sum=0; for(int x=i;x>0;x-=lowbit(x)) for(int y=j;y>0;y-=lowbit(y)) sum+=base[x][y]; return sum;}
注意提示
1.树状数组中一定不能有0元,如果题目中有要注意处理。通常是整体数据加1,这样后同时也要注意变化后的数据上限
2.树状数组可以用来求逆序数,实现方法使让数字成为树状数组的元素,比某个数小的数有多少就是这个数在数组中的前缀和
- 【数据结构】——树状数组的几种模型
- 数据结构—树状数组
- 数据结构——树状数组
- 树状数组区间求和的三种模型
- [树状数组] 区间求和的三种模型
- ACM常用模板——数据结构——树状数组
- 数据结构与算法复习(22)—— 树状数组
- hdu——1166(数据结构之树状数组的简单应用)
- POJ 3378——Crazy Thairs(树状数组+dp+高精度)数据结构优化的DP
- 数据结构----树状数组----子区间的和
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 详解树状数组三种模型
- 树状数组区间求和三种模型
- 树状数组求和三种模型
- 算法学习—树状数组
- Android学习之位图BitMap
- 古代文化与典故
- 我的成长—优化类(new数组)--2016.8.13
- LearnOpenGL学习笔记4:纹理
- 【数据结构】——树状数组的几种模型
- YYModel 简介与使用
- myBatis关于不允许空值属性的查询
- 人脸识别-再识
- Sring 字符串判断是否相同
- map写入文件及从文件读出
- c# 经验谈:巧用Expression表达式 解决类似于sql中 select in 的查询
- 傅立叶分析导论-5 傅里叶变换
- IE6IE7Firefox浏览器不兼容原因及解决办法