#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const ll N=1e5+5;
ll n,m,tr[N<<2],A[N],mark[N<<2];
void Build(ll l,ll r,ll p) {
if(l==r) tr[p]=A[l];
else {
ll mid=(l+r)/2,lc=2*p,rc=2*p+1;
Build(l,mid,lc);
Build(mid+1,r,rc);
tr[p]=tr[lc]+tr[rc];
}
}
void Add(ll l,ll r,ll k,ll cl,ll cr,ll p) {
if(cr<l||cl>r) return;
else {
if(cl>=l&&cr<=r) {
tr[p]+=k*(cl-cr+1);
if(cl!=cr) mark[p]+=k;
} else {
ll lc=2*p,rc=2*p+1,mid=(cl+cr)/2;
tr[lc]+=mark[p]*(mid-cl+1);
tr[rc]+=mark[p]*(cr-mid);
mark[lc]+=mark[p];
mark[rc]+=mark[p];
mark[p]=0;
Add(l,r,k,cl,mid,lc);
Add(l,r,k,mid+1,cr,rc);
tr[p]=tr[lc]+tr[rc];
}
}
}
ll Find(ll l,ll r,ll cl,ll cr,ll p) {
if(cr<l||cl>r) return 0;
else {
if(cl>=l&&cr<=r) return tr[p];
else {
ll lc=2*p,rc=2*p+1,mid=(cl+cr)/2;
tr[lc]+=mark[p]*(mid-cl+1);
tr[rc]+=mark[p]*(cr-mid);
mark[lc]+=mark[p];
mark[rc]+=mark[p];
mark[p]=0;
return Find(l,r,cl,mid,lc)+Find(l,r,mid+1,cr,rc);
}
}
}
int main() {
scanf("%lld%lld",&n,&m);
for(ll i=1; i<=n; ++i) scanf("%lld",&A[i]);
Build(1,n,1);
for(ll i=1; i<=m; ++i) {
ll t,x,y,k;
scanf("%lld",&t);
if(t==1) {
scanf("%lld%lld%lld",&x,&y,&k);
Add(x,y,k,1,n,1);
} else {
scanf("%lld%lld",&x,&y);
ll ans=Find(x,y,1,n,1);
printf("%lld\n",ans);
}
}
return 0;
}
跟着知乎用户 @ Pecco 的线段树模板打的,已过样例和手造数据,但哪里错了呢?