树状数组(单点修改区间查询)

树状数组(单点修改区间查询)_第1张图片

lowbit(重要!)

lowbit是用来取出二进制中最低位数的1所代表的二进制的值。
只需要记下代码就行了

int lowbit(int x){
	return x&(-x);
}

add单点修改前缀和

将一个树的最子节点修改,则其父节点也需要更改,父父节点也需要修改。x=x+lowbit(x)就是用来取出其父节点的。

void add(int x,int k){
	while(x<=n){
		sum[x]+=k;
		x=lowbit(x)+x;
	}
}

query查询前缀和

前缀和

https://blog.csdn.net/johnwayne0317/article/details/84928854

树状数组中的查询原数组前缀和

能查询原数组的前缀和,时间复杂度为O(nlogn)
查出其中每个范围内最父节点的值并相加

int count(int x){
	int cnt=0;
	while(x>0){
		cnt+=sum[x];
		x=x-lowbit(x);
	}
	return cnt;
}

题目链接

https://www.luogu.org/problemnew/show/P3368

代码

#include
#include 
#include 
#include 
#include 
using namespace std;
int sum[500010];
int n,m;
int lowbit(int x){
	return x&(-x);
}
void add(int x,int k){
	while(x<=n){
		sum[x]+=k;
		x=lowbit(x)+x;
	}
}

int count(int x){
	int cnt=0;
	while(x>0){
		cnt+=sum[x];
		x=x-lowbit(x);
	}
	return cnt;
}
int main(){
	memset(sum,0,sizeof(sum));
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		int tmp2;
		cin>>tmp2;
		add(i,tmp2);
		
	}
	for(int j=0;j<m;j++){
		int s;
		cin>>s;
		int x,k;
		cin>>x>>k;
		if(s==1){
			add(x,k);
		}else{
			cout<<count(k)-count(x-1)<<endl;
		}
	}
	return 0;
} 

你可能感兴趣的:(数据结构)