【模板】树状数组(详解)
来源:互联网 发布:小田切让 知乎 编辑:程序博客网 时间:2024/06/06 06:52
转自zP1nG
树状数组可以解决什么样的问题
对于包含n个元素的整数数组a,每次可以
1. C(i, j): 修改一个元素a[i] = j
2. Q(i): 询问前缀Si=a1+a2+…+ai的值
lowbit值
在说树状数组之前,我们不得不说一下lowbit值
设c[i]=a[i-2k+1]+…+a[i],其中k为i在二进制下末尾0的个数
令LOWBIT(i)=2^k
例如, i=1001010110010000, 则k=4
因为补码的原理是:正数变负数时,按位取反 末位加一
所以对于正数x 我们不难得到lowbit公式: lowbit(x)=x and -x
树状数组是一个动态维护前缀和的数据结构
网上最“火”的图应该是这个
修改操作
当修改c[x]时, 可能有很多c随之修改
例如,对于x=76=01001010,可以得到:
p1= 01001010
p2= 01001100
p3= 01010000
p4= 01100000
p5= 10000000
所以
•P1=x
•Pi+1=Pi+LOWBIT(Pi)
则需要依次修改C[p1],C[p2],…
询问操作
如何计算A[1]+…+A[x]?
首先累加C[x], 因为它的定义是以x结尾的连续和,它的连加起点是C[i-LOWBIT(i)+1]
因此问题转化为了求A[1]+…+A[i-LOWBIT(i)]
由此, 我们得到递推式
•P1=x
•Pi+1=Pi-LOWBIT(Pi)
则只需要累加C[p1], C[p2], …
清晰一点就像这样
P3374 【模板】树状数组1
代码模板
#include<bits/stdc++.h>using namespace std;int n,m,a[500001],b[500001],low[500001];inline void add(int x,int z){ for(int i=x;i<=n;i+=low[i]) b[i]+=z;}inline int qh(int x){ int ans=0; for(int i=x;i;i-=low[i])ans+=b[i]; return ans;}int x,y,z;int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)low[i]=i&(-i); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); add(i,a[i]); } for(int i=1;i<=m;++i){ scanf("%d%d%d",&x,&y,&z); if(x==1){ add(y,z); } else{ printf("%d\n",qh(z)-qh(y-1)); } } return 0;}
阅读全文
3 0
- 【模板】树状数组(详解)
- 树状数组(模板)
- 树状数组 (模板)
- 树状数组(模板)
- (树状数组)模板
- 树状数组(模板)
- 树状数组 (模板)
- 树状数组(模板+原理)
- 无题(树状数组模板)
- 初识树状数组(模板)
- 树状数组模板+poj1195(二维树状数组)
- 树状数组详解(转载)
- 树状数组详解(转)
- hdu4000(一维树状数组模板)
- hdu 1892(二维树状数组模板)
- hdu 3584 (三维树状数组模板 )
- 树状数组求逆序数(模板)
- 敌兵布阵(树状数组模板题)
- C/C++二叉树的创建与遍历
- 自定义气泡文字背景上下边距总是宽
- 使用RecyclerView实现两种不同Item布局
- C++类构造函数初始化列表
- spring boots JPA 使用MYSQL
- 【模板】树状数组(详解)
- 无限轮播+XListView
- 为微信开发填坑:微信网页支付的开发流程及填坑技巧
- Ambari 2.5.0安装包源码制作流程
- Spark 之 shuffle优化
- Winform的窗体美化心酸路
- IntelliJ:同时选中多列
- H5标签了解
- Unity Sahder 语法及注意事项