AC on #5-8
#include<bits/stdc++.h>
#define int long long
// #define double long double
#define ls 2*x
#define rs 2*x+1
using namespace std;
int n,q;
double sum[500009],tag[500009],fsum[500009],arr[100009];
//向上更新
void pushup(int x){
sum[x]=sum[ls]+sum[rs];
fsum[x]=fsum[ls]+fsum[rs];
}
//根据标记更新
void f(int x,int l,int r,double k){
tag[x]+=k;
fsum[x]+=2*k*sum[x]+(r-l+1)*k*k;
sum[x]+=(r-l+1)*k;
}
//标记下传
void pushdown(int x,int l,int r){
int mid=(l+r)>>1;
f(ls,l,mid,tag[x]);
f(rs,mid+1,r,tag[x]);
tag[x]=0;
}
//建树
void build(int x,int l,int r){
if(l==r){sum[x]=arr[l],fsum[x]=arr[l]*arr[l];return;}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(x);
}
//求区间和
double query(int x,int ql,int qr,int l,int r){
if(ql<=l&&r<=qr) return sum[x];
int mid=(l+r)>>1;
double res=0;
pushdown(x,l,r);
if(ql<=mid) res+=query(ls,ql,qr,l,mid);
if(qr>mid) res+=query(rs,ql,qr,mid+1,r);
return res;
}
//求区间平方和
double fquery(int x,int ql,int qr,int l,int r){
if(ql<=l&&r<=qr) return fsum[x];
int mid=(l+r)>>1;
double res=0;
pushdown(x,l,r);
if(ql<=mid) res+=query(ls,ql,qr,l,mid);
if(qr>mid) res+=query(rs,ql,qr,mid+1,r);
return res;
}
void update(int x,int ql,int qr,int l,int r,double k){
if(ql<=l&&r<=qr){
f(x,l,r,k);
return;
}
int mid=(l+r)>>1;
pushdown(x,l,r);
if(ql<=mid) update(ls,ql,qr,l,mid,k);
if(qr>mid) update(rs,ql,qr,mid+1,r,k);
pushup(x);
}
int op,xx,yy;
double kk;
signed main(){
cin>>n>>q;
for(int i=1;i<=n;i++) scanf("%lf",&arr[i]);
build(1,1,n);
for(int i=1;i<=q;i++){
scanf("%lld%lld%lld",&op,&xx,&yy);
if(op==1){
scanf("%lf",&kk);
update(1,xx,yy,1,n,kk);
}
else if(op==2) cout<<fixed<<setprecision(4)<<1.0*query(1,xx,yy,1,n)/(yy-xx+1)<<endl;
else{
double fangsum=fquery(1,xx,yy,1,n),nsum=query(1,xx,yy,1,n),xsum=query(1,xx,yy,1,n)/(yy-xx+1);
cout<<fixed<<setprecision(4)<<(fangsum-2*xsum*nsum+(yy-xx+1)*xsum*xsum)/(yy-xx+1)<<endl;
}
}
return 0;
}