Sol
容斥+画图理解
数组ca存的是修改区间覆盖当前点时应该加的值
数组cb存的是修改区间完全在当前点前面时对当前点的前缀和影响
当然还有其它情况
有时间的话会补图
另外一种方法
利用差分数组
写法可能更简洁
数学推导的思路比直接脑补容斥原理更简单一些
比如扩展到二维的 bzoj 3132
Code
// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;
const int N=200010;
int n,m;
LL a[N];
LL ca[N],cb[N];
int lowbit(int x){return x&(-x);}
void adda(int p,LL v){
for(int i=p;i<=n;i+=lowbit(i))
ca[i]+=v;
}
void addb(int p,LL v){
for(int i=p;i<=n;i+=lowbit(i))
cb[i]+=v;
}
LL sum(int x,int y){
LL ret=0;
for(int i=x-1;i;i-=lowbit(i)) ret+=cb[i]-1ll*(x-1)*ca[i];
for(int i=y;i;i-=lowbit(i)) ret+=1ll*y*ca[i]-cb[i];
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
adda(i,a[i]);
adda(i+1,-a[i]);
addb(i,(i-1)*a[i]);
addb(i+1,-i*a[i]);
}
int op,x,y;
LL z;
scanf("%d",&m);
while(m--){
scanf("%d%d%d",&op,&x,&y);
if(op==1){
scanf("%lld",&z);
adda(x,z);
adda(y+1,-z);
addb(x,1ll*(x-1)*z);
addb(y+1,-1ll*y*z);
}
if(op==2){
printf("%lld\n",sum(x,y));
}
}
return 0;
}