#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m;
struct SegmentTree {
int l,r;
ll sum,lazy;//区间和 lazy标记
#define l(p) (node[p].l)
#define r(p) (node[p].r)
#define sum(p) (node[p].sum)
#define lazy(p) (node[p].lazy)
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
} node[maxn*4];
void build(int p,int l,int r) {//传入结点编号p和对应区间[l,r]
l(p)=l;r(p)=r;
if(l==r) {//叶节点
scanf("%lld",&sum(p));
return;
}
int mid=l+r>>1;
build(ls(p),l,mid);//递归建左右子树
build(rs(p),mid+1,r);
sum(p)=sum(ls(p))+sum(rs(p));//更新区间和
}
void update(int p,ll val) {//对p结点的值增加val
sum(p)+=(r(p)-l(p)+1)*val;
lazy(p)+=val;
}
void pushdown(int p) {//下放标记
if(lazy(p)==0) return;//有标记才下放
update(ls(p),lazy(p));//传至左右子树
update(rs(p),lazy(p));
lazy(p)=0;//清空自身标记
}
void change(int p,int L,int R,ll val) {//区间修改 [L,R]增加val
if(l(p)>R||r(p)<L) return;//无交集
if(L<=l(p)&&R>=r(p)) return update(p,val);//该节点被完全覆盖
pushdown(p);//下放
change(ls(p),L,R,val);//递归修改
change(rs(p),L,R,val);
sum(p)=sum(ls(p))+sum(rs(p));//更新信息
}
ll query(int p,int L,int R) {
if(l(p)>R||r(p)<L) return 0;//无交集
if(L<=l(p)&&R>=r(p)) return sum(p);//被完全覆盖
pushdown(p);//下放
return query(ls(p),L,R)+query(rs(p),L,R);//左右子树和
}
int main() {
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--) {
int flag,l,r,val;
scanf("%d",&flag);
if(flag==1) scanf("%d%d%d",&l,&r,&val),change(1,l,r,val);
else scanf("%d%d",&l,&r),printf("%lld\n",query(1,l,r));
}
return 0;
}