普普通通的线段树做法
#include
using namespace std;
const int M=1e5+5;
#define lc(x) ((x)<<1)
#define rc(x) ((x)<<1|1)
#define int long long
int n,m;
int a[M],sm[M<<2],tag[M<<2];
void pushup(int x) { sm[x]=sm[lc(x)]+sm[rc(x)]; }
void build(int p,int l,int r){
if(l==r) { sm[p]=a[l];return; }
int mid=(l+r)>>1;
build(lc(p),l,mid),build(rc(p),mid+1,r);
pushup(p);
}
void f(int p,int l,int r,int k) { tag[p]+=k;sm[p]+=k*(r-l+1); }
void pushdown(int p,int l,int r) { int mid=(l+r)>>1;f(lc(p),l,mid,tag[p]),f(rc(p),mid+1,r,tag[p]),tag[p]=0; }
void update(int nl,int nr,int l,int r,int p,int k){
if(nl<=l&&r<=nr) { f(p,l,r,k);return; }
pushdown(p,l,r);
int mid=(l+r)>>1;
if(nl<=mid) update(nl,nr,l,mid,lc(p),k);
if(mid<nr) update(nl,nr,mid+1,r,rc(p),k);
pushup(p);
}
int query(int qx,int qy,int l,int r,int p){
int ans=0;
if(qx<=l&&r<=qy) return sm[p];
int mid=(l+r)>>1;
pushdown(p,l,r);
if(qx<=mid) ans+=query(qx,qy,l,mid,lc(p));
if(mid<qy) ans+=query(qx,qy,mid+1,r,rc(p));
return ans;
}
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(m--){
int if_case;
cin>>if_case;
int x,y,k;
switch (if_case){
case 1:cin>>x>>y>>k;update(x,y,1,n,1,k);break;
case 2:cin>>x>>y;cout<<query(x,y,1,n,1)<<endl;break;
}
}
return 0;
}