终极树状数组

树状数组及初步拓展。


接着提出新的问题:

A l r x把[l,r]加上x

Q l r 求[l,r]的总和


这该怎么办呢?显然先前所提出的方法已不再使用,我们深度分析:

令加x之前sum[i]=segma(a[i]),加x之后sum'[i]=segma(a[i]).

如果给[l,r]加上x,会对sum产生怎样的影响?

1.i<l   sum'[i]=sum[i]

2.l<=i<=r    sum'[i]=sum[i]+x*(i-l+1)=sum[i]+x*i-(l-1)*x

3.r<i  sum'[i]=sum[i]+x*(r-l+1)

显然,对于1,3我们可以很简单的解决,只需借助imos算法即可,那么2呢?

沿用往昔的分析思路:把变的拎出来,不变的固定。

那么对于sum'[i]=sum[i]+x*i-x*(l-1)

我们可以维护sum1[i]=x,sum2[i]=sum[i]-x*(l-1)

那么sum'[i]=i*sum1[i]+sum2[i]

而sum1[i],sum2[i]都不含有可变的量,可以用树状数组维护。


参考程序:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=110000;
int n;
struct BitTree{
	int a[maxn];
	int n;
	void init(int n){
		this->n=n;
		memset(a,0,sizeof(a));
	}
	void add(int x,int k){
		while (x<=n){
			a[x]+=k;
			x+=x&(-x);
		}
	}
	int query(int x){
		int sum=0;
		while (x>0){
			sum+=a[x];
			x-=x&(-x);
		}
		return sum;
	}
}bit0,bit1;
int main(){
	int T;
	scanf("%d%d",&n,&T);
	bit0.init(n);bit1.init(n);
	while (T--){
		char cmd;
		int L,R,x;
		scanf("\n%c%d%d",&cmd,&L,&R);
		if (cmd=='A'){
			scanf("%d",&x);
			bit0.add(L,-x*(L-1));
			bit1.add(L,x);
			bit0.add(R+1,x*R);
			bit1.add(R+1,-x);
		}else{
			int t=bit0.query(R)+bit1.query(R)*R;
			t-=bit0.query(L-1)+bit1.query(L-1)*(L-1);
			printf("%d\n",t);
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值