树状数组

对应线段树,补一下树状数组的笔记
某乎上写的不错的树状数组

1.树状数组原理

树状数组.png
蓝线为+ lowbit
绿线为-lowbit

树状数组最重要的原理

树状数组本质上是前缀和(差分)之类的巴拉巴拉

2.lowbit

不理解,背过吧....

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

3.修改点权(加减)

没必要往下传值,类似于线段树,直接在父节点行修改

void build(int x,int v){
	for(int i = x; i<=n; i+= lowbit(i)){
		tree[i]+=v;
	}
}

4.区间求和

前缀和的原理

int query(int s,int e){
	int ans1=0,ans2=0;
	for(int i = s - 1; i > 0; i-=lowbit(i)) {
		ans1+= tree[i];
	}
	for(int i = e; i > 0; i-=lowbit(i)) {
		ans2+=tree[i];
	}
	return ans2-ans1;
}

树状数组 1模板

//# 树状数组1 
#include<iostream>
#include<cstdio>
using namespace std;
const int N=5e5+10;
int tree[N];
int sum[N],a[N];
int n,m; 
int lowbit(int x){
	return x&(-x);
}
int query(int s,int e){
	int ans1=0,ans2=0;
	for(int i = s - 1; i > 0; i-=lowbit(i)) {
		ans1+= tree[i];
	}
	for(int i = e; i > 0; i-=lowbit(i)) {
		ans2+=tree[i];
	}
	return ans2-ans1;
}
void build(int x,int v){
	for(int i = x; i<=n; i+= lowbit(i)){
		tree[i]+=v;
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		add(i,a[i]);
	}
	for(int i= 1,tpy,x,w; i <=m;i++){
		scanf("%d%d%d",&tpy,&x,&w);
		if(tpy==1)
			build(x,w);
		else
			printf("%d\n",query(x,w));
	}
	return 0;
}

5.区间加

差分的原理前缀和(貌似不怎么准确)
给x的父亲加上,然后给y+1的父亲减去
这样相当于进行了变区间加的操作一次给x后面的都加k,第二次给y+1后面的都减去k,把x多修改的区间都修回来

ll add(ll x,ll v){
	while(x <=n ){
		tree[x]+=v;
		x+=lowbit(x);
	} 
}
scanf("%lld%lld%lld",&x,&y,&k);
	add(x,k),add(y+1,-k);
//x---y的区间都加+k

数组数组2 模板

#include<iostream>
#include<cstdio>
#define ll long long 
using namespace std;
const int N=5e5+10; 
ll a[N],tree[N];
int n,m;
ll lowbit(ll x){
	return x&(-x);
}
ll add(ll x,ll v){
	while(x <=n ){
		tree[x]+=v;
		x+=lowbit(x);
	} 
}
ll quert(ll x){
	ll ans=0;
	while(x>=1){
		ans+=tree[x];
		x-=lowbit(x); 
	}
	return ans;
}
int main(){
	scanf("%lld%lld",&n,&m);
	for(int i = 1; i <=n ; i++) {
		scanf("%d",&a[i]);
		add(i,a[i]-a[i-1]); 
	} 
	int tpy;
	ll x,y,k;
	for(int i = 1;i <= m ;i++){
		cin>>tpy;
		if(tpy==1){
			scanf("%lld%lld%lld",&x,&y,&k);
			add(x,k),add(y+1,-k);
		}
		if(tpy==2){
			scanf("%lld",&x);
			printf("%lld\n",quert(x));
		}
	}
	return 0;
}
	
posted @ 2020-11-01 21:31  Imy_bisLy  阅读(113)  评论(0编辑  收藏  举报