#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100005;
int a[maxn];
struct N{
int l,r;
ll pre,add;
}node[4*maxn+5];
void build(int p,int l,int r){//区间编号p
node[p].l = l; node[p].r = r;
if(l==r){//叶子结点直接赋值
node[p].pre = a[l];
return ;
}
int mid = l+r >>1;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
node[p].pre = node[p*2].pre + node[p*2+1].pre;//维护区间和
}
void spread(int p){
if(node[p].add){//如果标记不为0 向下传递
node[2*p].pre+=(node[2*p].r - node[2*p].l + 1)*node[p].add;
node[2*p+1].pre+=(node[2*p+1].r - node[2*p+1].l + 1)*node[p].add;
node[2*p].add+= node[p].add;
node[2*p+1].add+= node[p].add;
node[p].add = 0;
}
}
void change(int p,int l,int r,int v){
if(node[p].l>=l&&node[p].r<=r){//区间被覆盖 就对其进行修改
node[p].pre+=(ll)v*(node[p].r-node[p].l+1);
node[p].add+= v; //加上懒惰标记
return ;
}
spread(p);//没有覆盖 下放懒惰标记 考虑儿子区间可能因为懒惰标记存在而没有修改
int mid = node[p].l + node[p].r>>1;
if(l<=mid)change(p*2,l,r,v);
if(r>mid)change(p*2+1,l,r,v);
node[p].pre = node[2*p].pre + node[2*p+1].pre;
}
ll query(int p,int l,int r){
if(l<=node[p].l&&r>=node[p].r){//被覆盖 返回值
return node[p].pre;
}
spread(p);
ll ans = 0;
int mid = node[p].r+node[p].l>>1;
if(l<=mid)ans+=query(p*2,l,r);
if(r>mid)ans+=query(p*2+1,l,r);
return ans;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
while(m--){
int op,l,r,k;
scanf("%d %d %d",&op,&l,&r);
if(op==1){
scanf("%d",&k);
change(1,l,r,k);
}else {
printf("%lld\n",query(1,l,r));
}
}
return 0;
}