#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
struct node
{
ll l,r,sum;
ll lazy; //懒标记
}tree[1000010];
ll a[1000010];
ll n,m;
void push_down(ll i)
{
if(tree[i].lazy!=0)
{
tree[i<<1].lazy+=tree[i].lazy;
tree[i<<1|1].lazy+=tree[i].lazy;
ll mid=tree[i].l+tree[i].r>>1;
tree[i<<1].sum+=tree[i].lazy*(mid-tree[i<<1].l+1);
tree[i<<1|1].sum+=tree[i].lazy*(tree[i<<1|1].r-mid);
tree[i].lazy=0;
}
return ;
}
void build(ll i,ll l,ll r)
{
tree[i].l=l,tree[i].r=r;
if(l==r)//如果他的左孩子下标与右孩子下标相同说明是叶子结点,赋值后返回;
{
tree[i].sum=a[l];
return ;
}
ll mid=l+r>>1;
build(i<<1,l,mid);//以左孩子为根结点建树
build(i<<1|1,mid+1,r);//以有孩子为根结点建树
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;//父亲结点的sum是左孩子sum和右孩子sum的和;
}
void add(ll i,ll l,ll r,ll k)//给区间[l,r]中的每个元素加上k;
{
if(tree[i].l>=l&&tree[i].r<=r)//访问的结点完全被包含再区间[l,r]内,更新该结点的值,添加懒标记;
{
tree[i].sum+=k*(tree[i].r-tree[i].l+1);
tree[i].lazy+=k;
return ;
}
push_down(i);//给该结点的左右孩子均添加懒标记;
if(tree[i<<1].r>=l)//如果左孩子与区间[l,r]有交集,更改该交集的值;
add(i<<1,l,r,k);
if(tree[i<<1|1].l<=r)//如果右孩子与区间[l,r]有交集,更改该交集的值;
add(i<<1|1,l,r,k);
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;父亲结点的sum是左孩子sum和右孩子sum的和
return ;
}
ll seek(ll i,ll l,ll r)//查询区间[l,r]所有元素的和
{
if(tree[i].l>=l&&tree[i].r<=r)//如果所访问结点被完全包括在区间[l,r]中,返回;
return tree[i].sum;
push_down(i);//该结点已经本访问过了,接下来有可能访问其子节点,所以需要更新该子结点的值与懒标记;
ll s=0;
if(tree[i<<1].r>=l)//左孩子与区间[l,r]有交集,访问左孩子结点
s+=seek(i<<1,l,r);
if(tree[i<<1|1].l<=r)//右孩子与区间[l,r]有交集,访问右孩子结点
s+=seek(i<<1|1,l,r);
return s;
}
int main()
{
cin>>n>>m;
for(ll i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
int f=0;
ll l,r,k;
for(ll i=1;i<=m;i++)
{
cin>>f;
if(f==1)
{
cin>>l>>r>>k;
add(1,l,r,k);
}
else
{
cin>>l>>r;
cout<<seek(1,l,r)<<endl;
}
}
return 0;
}