#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int N = 10000 + 10;
const int inf = 0x3f3f3f3f;
ll tree1[N<<2],tree2[N<<2],lazy1[N<<2],lazy2[N<<2];// tree1维护区间和 tree2维护平方和
// lazy1 维护加法 lazy2 维护乘法
ll a[N];
void build(int p,int l,int r)
{
if(l==r)
{
tree1[p]=a[l];
tree2[p]=a[l]*a[l];
return ;
}
int mid=l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
tree1[p]=tree1[p<<1]+tree1[p<<1|1];
tree2[p]=tree2[p<<1]+tree2[p<<1|1];
return ;
}
void pushdown(int p,int l,int r)
{
int mid=l+r>>1;
lazy1[p<<1] += lazy1[p];
lazy1[p<<1|1]+= lazy1[p];
lazy2[p<<1] *= lazy2[p];
lazy2[p<<1|1]*= lazy2[p];
tree2[p<<1] *= lazy2[p]*lazy2[p];
tree2[p<<1] += 2*lazy1[p]*lazy2[p]*tree1[p<<1] + lazy1[p]*lazy1[p]*(mid-l+1);
//tree2[p<<1]=tree2[p<<1]*(lazy2[p]^2)+2*lazy1[p]*lazy2[p]*tree1[p]+(mid-l+1)*(lazy1[p]^2)
tree2[p<<1|1] *= lazy2[p]*lazy2[p];
tree2[p<<1|1] += 2*lazy1[p]*lazy2[p]*tree1[p<<1|1] + lazy1[p]*lazy1[p]*(r-mid);
tree1[p<<1] *= lazy2[p];
tree1[p<<1] += lazy1[p]*(mid-l+1);
tree1[p<<1|1] *= lazy2[p];
tree1[p<<1|1] += lazy1[p]*(r-mid);
lazy1[p]=0;
lazy2[p]=1;
return ;
}
void change1(int p,int l,int r,int x,int y,ll w)//区间修改,把x->y 区间每个数加个w
{
if(x<=l&&r<=y)
{
tree2[p] += 2*w*tree1[p]+w*w*(r-l+1);
tree1[p] += w*(r-l+1);
lazy1[p] += w;
return ;
}
if(lazy1[p]!=0||lazy2[p]!=1) pushdown(p,l,r);//lazy往下传
int mid=l+r>>1;
if(x<=mid) change1(p<<1,l,mid,x,y,w);
if(y>mid) change1(p<<1|1,mid+1,r,x,y,w);
tree1[p]=tree1[p<<1]+tree1[p<<1|1];
tree2[p]=tree2[p<<1]+tree2[p<<1|1];
}
void change2(int p,int l,int r,int x,int y,ll w)//区间修改,把x->y 区间每个数乘个w
{
if(x<=l&&r<=y)
{
tree2[p] *= w*w;
tree1[p] *= w;
lazy1[p] *= w;
lazy2[p] *= w;
return ;
}
if(lazy1[p]!=0||lazy2[p]!=1) pushdown(p,l,r);//lazy往下传
int mid=l+r>>1;
if(x<=mid) change2(p<<1,l,mid,x,y,w);
if(y>mid) change2(p<<1|1,mid+1,r,x,y,w);
tree2[p]=tree2[p<<1]+tree2[p<<1|1];
tree1[p]=tree1[p<<1]+tree1[p<<1|1];
}
ll calc1(int p,int l,int r,int x,int y)//l r表示左右区间 ,x y 表示要查询的区间
{
if(x<=l&&r<=y) return tree1[p];
if(lazy1[p]!=0||lazy2[p]!=1) pushdown(p,l,r);
int mid=l+r>>1;
if(y<=mid) return calc1(p<<1,l,mid,x,y);
if(x>mid) return calc1(p<<1|1,mid+1,r,x,y);
return calc1(p<<1,l,mid,x,y)+calc1(p<<1|1,mid+1,r,x,y);
}
ll calc2(int p,int l,int r,int x,int y)//l r表示左右区间 ,x y 表示要查询的区间
{
if(x<=l&&r<=y) return tree2[p];
if(lazy1[p]!=0||lazy2[p]!=1) pushdown(p,l,r);
int mid=l+r>>1;
if(y<=mid) return calc2(p<<1,l,mid,x,y);
if(x>mid) return calc2(p<<1|1,mid+1,r,x,y);
return calc2(p<<1,l,mid,x,y)+calc2(p<<1|1,mid+1,r,x,y);
}
int main()
{
for (int i=0;i<=10000*4;i++) lazy2[i]=1;
memset(lazy1,0,sizeof(lazy1));
memset(tree1,0,sizeof(tree1));
memset(tree2,0,sizeof(tree2));
int n,q;
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
for (int i=1;i<=q;i++)
{
ll op,l,r,w;
scanf("%lld",&op);
if(op==3)//区间 l -> r 乘x
{
scanf("%lld%lld%lld",&l,&r,&w);
change2(1,1,n,l,r,w);
}
else if(op==4)//区间 l -> r 加x
{
scanf("%lld%lld%lld",&l,&r,&w);
change1(1,1,n,l,r,w);
}
else if(op==1)// 查询区间 l -> r的和
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",calc1(1,1,n,l,r));
}
else// 查询区间 l -> r的平方和
{
scanf("%lld%lld",&l,&r);
printf("%lld\n",calc2(1,1,n,l,r));
}
}
return 0;
}