蒟蒻の树状数组学习总结

定义

树状数组(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;
}
posted @ 2020-07-31 13:47  小罐猹  阅读(105)  评论(0编辑  收藏  举报