蒟蒻の树状数组学习总结
定义
树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询)。
这种数据结构(算法)并没有C++和Java的库支持,需要自己手动实现。在Competitive Programming的竞赛中被广泛的使用。树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决。相比较而言,树状数组效率要高很多。
解决问题
可以解决大部分基于区间上的更新以及求和问题。
模板
#include<iostream>
using namespace std;
int n,m,i,num[100001],t[200001],l,r;//num:原数组;t:树状数组
int lowbit(int x){
return x&(-x);
}
void change(int x,int p){//将第x个数加p
while(x<=n){
t[x]+=p;
x+=lowbit(x);
}
return;
}
int sum(int k){//前k个数的和
int ans=0;
while(k>0){
ans+=t[k];
k-=lowbit(k);
}
return ans;
}
int ask(int l,int r){//求l-r区间和
return sum(r)-sum(l-1);
}
int main(){
cin>>n>>m;
for(i=1;i<=n;i++){
cin>>num[i];
change(i,num[i]);
}
for(i=1;i<=m;i++){
cin>>l>>r;
cout<<ask(l,r)<<endl;
}
return 0;
}
例题
P3374 【模板】树状数组 1
思路
一道涉及区间修改的
简单模板题,结果本蒟蒻居然还错了两次,一次错在数组开小,第二次发现超时了,结果发现num数组根本不需要!直接将值作为一个变量输入并存入树状数组就行了qwq
失误总结
不必要的变量千万别瞎加!不然会拖慢读入的速度
C o d e Code Code
#include<iostream>
using namespace std;
int n,m,i,a,t[500010],l,r;//num:原数组;t:树状数组
int ord,x,k;
int lowbit(int x){
return x&(-x);
}
void change(int x,int p){//将第x个数加p
while(x<=n){
t[x]+=p;
x+=lowbit(x);
}
return;
}
int sum(int k){//前k个数的和
int ans=0;
while(k>0){
ans+=t[k];
k-=lowbit(k);
}
return ans;
}
int ask(int l,int r){//求l-r区间和
return sum(r)-sum(l-1);
}
int main(){
cin>>n>>m;
for(i=1;i<=n;i++){
cin>>a;
change(i,a);
}
for(i=1;i<=m;i++){
cin>>ord;
if(ord==1){
cin>>x>>k;
change(x,k);
}else{
cin>>l>>r;
cout<<ask(l,r)<<endl;
}
}
return 0;
}
她透过我的血,看到了另一抹殷红