P3372
#include<bits/stdc++.h>
using namespace std;
#define ls(p) p<<1//zdy
#define rs(p) p<<1|1
const int maxn=100000;
int a[1000000];
struct tree{
int data;
}t[maxn*4];
int add[100000];//lazy数组
void build(int p,int l,int r) {
if(l==r){
t[p].data=a[l];
return;
}
int mid=(l+r)/2;
build(ls(p),l,mid),build(rs(p),mid+1,r);
t[p].data=t[p*2].data+t[p*2+1].data;
}
void ad(int k,int l,int r,int v){//加标记的函数
add[k]+=v;//打标记
t[k].data+=(r-l+1)*v;
}
void pushdown(int k,int l,int r,int mid){//当前节点,左端点,右端点,中端点
if(add[k]==0) return //没有标记;
ad(ls(k),l,mid,add[k]);
ad(rs(k),mid+1,r,add[k]);//下传
add[k]=0;//下传后,原标记删除;
}
void modify(int k,int l,int r,int x,int y,int v){//当前节点,当前递归左端点,右端点,需要添加的区间,以及需要添加的值
if(l>=x&&r<=y) return ad(k,l,r,v);//递归到目标区间的子区间,不在向下递归,直接标记
int mid=(l+r)>>1;
pushdown(k,l,r,mid);
if(x<=mid) modify(k*2,l,mid,x,y,v);//递归左子树
if(mid<y) modify(k*2+1,mid+1,r,x,y,v);//递归右子树
t[k].data=t[ls(k)].data+t[rs(k)].data;
}
int query(int k,int l,int r,int x,int y){//基本上与modify函数语句一样,只不过需要·1
if(l>=x&&r<=y) return add[k];
int mid=(l+r)>>1,res=0;
pushdown(k,l,r,mid);//标记下传
if(x<=mid) res+=query(k*2,l,mid,x,y);//递归左子树
if(mid<y) res+=query(k*2+1,mid+1,r,x,y);//递归右子树
return res;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
while(m--){
int op;
cin>>op;
if(op==1){
int x,y,k;
cin>>x>>y>>k;
modify(1,1,n,x,y,k);
}
if(op==2){
int x,y;
cin>>x>>y;
cout<<query(1,1,n,x,y)<<endl;
}
}
return 0;
}