树状数组——三种用法详解
来源:互联网 发布:mac os10.7.5如何升级 编辑:程序博客网 时间:2024/06/06 00:38
树状数组
- 树状数组可以视为线段树的一个分枝 树状数组能做的题 线段树基本都能做
- 但线段树的代码量比较少 容易实现
- 思想用lowbit 动态维护某一区间的和 求lowbit: lowbit= k & (-k);
- 在维护和求值时用到了二分的思想
- 线段树的题基本可以分三种情况
1.点更新 区间查询
2.区间更新 点查询
3.区间更新 区间查询
一,点更新 区间查询(最基本的用法)
在这种用法中 c数组里存储的每个值就代表某一段区间的和 插入点时向右维护c数组里的值(因为后面的数代表的前i项和中才又可能包含此时的值)
用求和函数求得前n项和(也称前缀和)
void add(int num,int value){ while(num<=n) { c[num]+=value; num+=num&-num; }}int getsum(int num)//1~num的区间和{ int sum=0; while(num) { sum+=c[num]; num-=num&-num; } return sum;}}
二,区间更新 点查询
说到区间更新 就不得不先讲数组的区间更新
我们要用数组更新一个区间(l r) 可以在区间左端处+value 右端点处-value
比如说 数组c长度为5 开始全部为0
我们想让2~4区间的数值都加2 只需让c[2]+=2 c[5]-=2 那么数组就变成了 0 2 0 0 -2 0
当我们想访问某一个数的时候 求c数组的前n项和 即从这个数对应的下标开始 求和到最左端 向左求和
1的值为c[1]=0 2的值为c[2]+c[1]=2 3的值为c[3]+c[2]+c[1]=2
5的值为c[5]+c[4]+c[3]+c[2]+c[1]=0 6的值为c[6]+c[5]+c[4]+c[3]+c[2]+c[1]=0
这样我们通过求和得出一个数的复杂度为On
而且可以得到 c[i]=a[i]+a[i-1] 所以c数组也叫差分数组
树状数组和数组的更新的思想是一样的 因为树状数组求和的复杂度低 只有log(n) 所以可以视作数组的优化
同时也是向右更新 向左查询
void add(int num,int v){ while(num <= n) { c[num] += v; num += num&(-num); }}int getsum(int num){ int sum = 0; while( num > 0 ) { sum += c[num]; num -= num&(-num); } return sum;}
上面的这种方法是博客上比较常用的 我们的第三者方法也要用到
但是同样的 我们在更新区间的时候也可以向左更新 向右查询 只是换了种思路 不再赘述
三,区间更新 区间查询
在查询一段区间的时候 我们有
a[1]+a[2]+…+a[n]
= (c[1]) + (c[1]+c[2]) + … + (c[1]+c[2]+…+c[n])
= n*c[1] + (n-1)*c[2] +… +c[n]
= n * (c[1]+c[2]+…+c[n]) - (0*c[1]+1*c[2]+…+(n-1)*c[n])
这里面的c数组和上面提到的一样 结果中的前半部分容易得到 而为了求后面的部分 我们可以再维护一个b数组 使得b[i]=(i-1)*c[i] 每当做区间修改的时候 就同时维护在两个区间 保持复杂度不变
void update(int int *a,int x,int v){ while(x<=n) { a[x]+=v; x += x&(-x); }}int getsum(int int *a,int x){ int sum=0; while(x>0) { sum+=a[x]; x -= (x&(-x)); } return sum;}
当更新(x,y)区间的时候
update( c , y+1 , -z ); update( c , x , z ); update( b , y+1, -z*(y+1) ); update( b , x , z*x );
最后求区间和时
sum = getsum(c,y)*(y+1) - getsum(c,x-1)*x - getsum(b,y) + getsum(b,x-1);
- 树状数组——三种用法详解
- 详解树状数组三种模型
- 树状数组三种写法
- 树状数组—介绍
- 树状数组—改段求段
- 树状数组—改段求点
- 数据结构—树状数组
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组区间求和三种模型
- 树状数组的三种操作
- 树状数组求和三种模型
- 树状数组的三种模式
- 树状数组(三)
- 树状数组(代码详解)
- 面向对象基础
- hdu3658 How many words 矩阵递推分析
- Ant学习笔记(一)-Ant入门
- Spring 内容总结
- 位图
- 树状数组——三种用法详解
- 微信小程序支付中的prepay_id获取方法,以及微信支付统一签名算法闭坑
- 最长回文子串manacher算法
- Win/CentOS/MacOS Chrome/Firefox/IE/Safari DNS缓存时间与刷新
- JS事件循环详解
- C. Fixing Typos----栈
- ng-grid双选盒子
- PLC编程全科班+人机界面编程+电机+变频器通信培训
- Andrid studio 引用多个module时jar包重复的解决