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