树状数组学习笔记
树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
这种数据结构(算法)并没有C++和Java的库支持,需要自己手动实现。在Competitive Programming的竞赛中被广泛的使用。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。
以上内容摘自百度。
树状数组是一种可以求前缀和的数据结构,寒假学习之后,做了几个题,借本文来总结一下,树状数组的知识。
lowbit函数背就可以了。
luogu树状数组1模板
#include<iostream> #include<cstdio> using namespace std; int tree[500001],haha[500001],f1,f2,n,m,num; int lowbit(int x) { return x & -x; } void add(int x,int k) { while(k<=n) { tree[k]+=x; k+=lowbit(k); } return ; } int sum(int x) { int ans=0; while(x!=0) { ans+=tree[x]; x-=lowbit(x); } return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&f1); add(f1,i); } for(int i=1;i<=m;i++) { scanf("%d",&f1); if(f1==1) { scanf("%d%d",&f1,&f2); add(f2,f1); continue; } else { scanf("%d%d",&f1,&f2); num++; haha[num]=sum(f2)-sum(f1-1); } } for(int i=1;i<=num;i++) printf("%d\n",haha[i]); return 0; }
luogu 树状数组2 代码
#include<iostream> #include<cstdio> using namespace std; int tree[500001],haha[500001],f1,f2,f3,n,m,num; int a[500001]; int lowbit(int x) { return x & -x; } void add(int x,int k) { while(k<=n) { tree[k]+=x; k+=lowbit(k); } return ; } int sum(int x) { int ans=0; while(x!=0) { ans+=tree[x]; x-=lowbit(x); } return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); add(a[i]-a[i-1],i); } for(int i=1;i<=m;i++) { scanf("%d",&f1); if(f1==1) { scanf("%d%d%d",&f1,&f2,&f3); add(f3,f1); add(-f3,f2+1); } else { scanf("%d",&f1); num++; haha[num]=sum(f1); } } for(int i=1;i<=num;i++) printf("%d\n",haha[i]); return 0; }