树状数组原理及模板

树状数组:

一. 作用:

1. 处理单点修改以及前缀查询

2. 特殊情况的区间修改与区间查询

二. 复杂度

修改: O(logn)
查询: O(logn)
空间: O(n)

三. 具体实现

生成

C[i]=Σa[j] (i-2^k<j<=i)
j ∈ (i-lowbit(i) , i);
lowbit(i) = (x & (-x))

int lowbit(int x) {return x&-x;}
int work(int x) {int sum=0; for (;x;x-=lowbit(x)) sum+=C[x]; return sum;}
int Query(int l,int r) {return sum(r)-sum(l-1);}
C[1]=a[1];
C[2]=a[1]+a[2];
C[3]=a[3];
C[4]=a[1]+a[2]+a[3]+a[4];
C[5]=a[5];
C[6]=a[5]+a[6];
C[7]=a[7];
C[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];

当ai增加x时如何修改C

(1) 令C[i]+=x。
(2) i+=lowbit(i)。
(3) 若i>n,退出,否则执行(1)。

void change(int i,int x){
    for (; i<=n; i+=lowbit(i)) C[i]+=x;
} 


区间增加,单点查询

令b[i]=a[i]-a[i-1]。
a[x]=∑b[j] (j<=x)
修改复杂度:O(1),查询复杂度(对b维护一个前缀和):O(1)


区间增加,区间查询和

b数组相关与上题相同
ans=(Σb[i])(i<=l)*(r-l+1)-Σ(b[i]i)(l<i<=r)+(Σb[i])(l<i<=r)(r+1)

int a[10010];//数据 
int b[10010];//a[i]-a[i-1] 
int c[10010];//树状数组核心 

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

void update(int x) {//更新单个c[x]
	c[x]=0; 
	for(int j=x-lowbit(x);j<=x;j++){
		c[x]+=a[j];
	}
}
void change(int i,int x) {//将a[i]的值增加x,并修改所有相关的c的值 
//	a[i]+=x;
	for(;i<=n;i+=lowbit(i))//n为数据的个数(a的长度) 
		c[i]+=x;
}

//单点修改,区间查询和 (35~43)
int preSum(int x) {//求前缀和 
	int sum=0;
	for(;x;x-=lowbit(x))
		sum+=c[x];
	return sum;
}
int query(int l,int r){
	return preSum(r)-preSum(l-1);
}

//区间增加,单点查询 (46~62)
int preB[10010];
void init() {
	preB[0]=0;
	for(int i=1;i<=n;i++){
		b[i]=a[i]-a[i-1];
		preB[i]=preB[i-1]+b[i];
	}
}
void modify(int l,int r,int v) {//[l,r]+v 
	b[l]+=v;
	b[r+1]-=v;
	for(int i=l;i<r+1;i++)
		preB[i]+=v;
}
int query(int x) {///查询a[x] 
	return preB[x];
}

//区间增加,区间查询和 (65~87)
int preB[10010];
void init() {
	preB[0]=0;
	for(int i=1;i<=n;i++){
		b[i]=a[i]-a[i-1];
		preB[i]=preB[i-1]+b[i];
	}
}
void modify(int l,int r,int v) {//[l,r]+v 
	b[l]+=v;
	b[r+1]-=v;
	for(int i=l;i<r+1;i++)
		preB[i]+=v;
}
int bii(int l,int r){
	int ans=0;
	for(int i=l;i<r+1;i++)
		ans+=b[i]*i;
	return ans;
}
int query(int l,int r) {
	return preB[l]*(r-l+1) - bii(l+1,r) + (preB[r+1]-preB[l]) * (r+1);
} 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值