#define lc p<<1
#define rc p<<1|1
const int N =100005;
int n,m;vector<int>nums;
struct node{
int l,r,sum,add;
}tr[4*N];
void pushup(int p){
tr[p].sum=tr[lc].sum+tr[rc].sum;
}
void pushdown(int p){
if(tr[p].add){
tr[lc].sum+=tr[p].add*(tr[lc].r-tr[lc].l+1);//左子树的sum更新
tr[rc].sum+=tr[p].add*(tr[rc].r-tr[rc].l+1);//右子树的sum更新
tr[lc].add+=tr[p].add;
tr[rc].add+=tr[p].add;
tr[p].add=0;
//更新完sum后更新懒标记
}
}
void built(int p,int l,int r){//建树不需考虑懒标记
tr[p]={l,r,nums[l]};//传入的参数仅仅是需要的东西,tr是为了建树
if(l==r) return;//到底了 不需要向下查询了
int m=l+r>>1;//获取分割点 便于分块
built(lc,l,m);//左子树 lc是其左子树编号 实际区间为l--m
built(rc,m+1,r);//右子树 同理 注意m+1
pushup(p);// // 合并左右子节点的统计值,更新父节点 p 的 sum
}
void change(int p,int x,int y,int k){//在区间(x,y)更改数据
if(x<=tr[p].l&&tr[p].r<=y){//此节点的左右区间在内部
tr[p].sum+=k*(tr[p].r-tr[p].l+1);
tr[p].add+=k;//懒标记
return;
}
int m=tr[p].l+tr[p].r>>1;//裂开之后会对儿子递归了 此时懒标记给下发过去
pushdown(p);
if(x<=m) change(lc,x,y,k);
if(y>m) change(rc,x,y,k);
pushup(p);//完成后全部上发过去更新
}
int query(int p,int x,int y){
int sum=0;
if(x<=tr[p].l&&tr[p].r<=y){
return tr[p].sum;
}
int m=tr[p].l+tr[p].r>>1;//依旧分裂处理懒标记
pushdown(p);
if(x<=m) sum+=query(lc,x,y);
if(y>m) sum+=query(rc,x,y);
return sum;
}
void solve(){
cin>>n>>m;
nums.resize(n+1);
for(int i=1;i<=n;i++)cin>>nums[i];
built(1,1,n);
while(m--){
int x;cin>>x;
if(x==1){
int l,r,k;cin>>l>>r>>k;
change(1,l,r,k);
}else{
int l,r;cin>>l>>r;
cout<<query(1,l,r)<<endl;
}
}
}