/*
https://ac.nowcoder.com/acm/contest/917/J
线段树维护区间的每个平方和
*/
#include
using namespace std;
typedef long long LL;
const int N=1e5+100;
LL tree1[N<<2],tree2[N<<2],lazy[N<<2];
void push_up(int k)
{
tree1[k]=tree1[k<<1]+tree1[k<<1|1];
tree2[k]=tree2[k<<1]+tree2[k<<1|1];
}
void build(int l,int r,int k)
{
lazy[k]=0;
if(l==r){
scanf("%lld",&tree1[k]);
tree2[k]=tree1[k]*tree1[k];
return;
}
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
push_up(k);
}
void push_down(int k,int len)
{
if(lazy[k]){
tree2[k<<1]+=(len-(len>>1))*lazy[k]*lazy[k]+2*tree1[k<<1]*lazy[k];
tree2[k<<1|1]+=(len>>1)*lazy[k]*lazy[k]+2*lazy[k]*tree1[k<<1|1];
tree1[k<<1]+=(len-(len>>1))*lazy[k];
tree1[k<<1|1]+=(len>>1)*lazy[k];
lazy[k<<1]+=lazy[k];
lazy[k<<1|1]+=lazy[k];
lazy[k]=0;
}
}
void update(int x,int y,LL z,int l,int r,int k)
{
if(x<=l&&y>=r){
lazy[k]+=z;
tree2[k]+=(r-l+1)*(z*z)+(2*z*tree1[k]);//注意这里
tree1[k]+=(r-l+1)*z;
return;
}
push_down(k,r-l+1);
int mid=(l+r)>>1;
if(x<=mid) update(x,y,z,l,mid,k<<1);
if(y>mid) update(x,y,z,mid+1,r,k<<1|1);
push_up(k);
}
LL query(int x,int y,int id,int l,int r,int k)
{
if(x<=l&&y>=r){
if(id==1) return tree1[k];
else return tree2[k];
}
push_down(k,r-l+1);
int mid=(l+r)>>1;
LL sum=0;
if(x<=mid) sum+=query(x,y,id,l,mid,k<<1);
if(y>mid) sum+=query(x,y,id,mid+1,r,k<<1|1);
return sum;
}
int main()
{
int n,q;
scanf("%d %d",&n,&q);
build(1,n,1);
while(q--){
int id,l,r;
scanf("%d %d %d",&id,&l,&r);
if(id==1){
LL x;
scanf("%lld",&x);
update(l,r,x,1,n,1);
}
else{
LL a=query(l,r,1,1,n,1);
LL b=query(l,r,2,1,n,1);
printf("%lld\n",(a*a-b)/2);
}
}
return 0;
}