#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;
}