在做一道整体二分的题目的时候遇到了这种区间修改区间查询的树状数组,感觉用起来手感不错就拿来了。证明的话,那其实不重要,会用就好了
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 500000
#define LL unsigned long long
using namespace std;
int n,m;
LL a[maxn],sum[maxn],c1[maxn],c2[maxn];
void update(int x,LL y){
for(int i=x;i<=n;i+=i&(-i))
c1[i]+=y,c2[i]+=(LL)x*y;
}
LL query(int x){
LL ans=0;
for(int i=x;i>0;i-=i&(-i)){
ans+=(x+1)*c1[i]-c2[i];
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%llu",a+i),sum[i]=sum[i-1]+a[i];
int pos,a,b;LL c;
while(m--){
scanf("%d%d%d",&pos,&a,&b);
if(pos==1){
scanf("%llu",&c);
update(a,c),update(b+1,-c);
}else{
printf("%llu\n",query(b)-query(a-1)+sum[b]-sum[a-1]);
}
}
return 0;
}