#include<cstdio>
#include<algorithm>
#define N 400005
#define int long long
#define lc p<<1
#define rc p<<1|1
#define mm (l+r)/2
using namespace std;
struct segementtree{
int l,r;
int su,pf;
}s[N];
int n,m;
void pushup(int p){
s[p].su=(s[lc].su+s[rc].su);
s[p].pf=(s[lc].pf+s[rc].pf);
}
void build(int p,int l,int r){
s[p].l=l,s[p].r=r;
if(l==r){
int a;
scanf("%lld",&a);
s[p].su=a;
s[p].pf=a*a;
return;
}
build(lc,l,mm);
build(rc,mm+1,r);
pushup(p);
}
void add(int p,int l,int r,int v){
if(s[p].l>r||s[p].r<l)return;
if(s[p].l>=l&&s[p].r<=r){
s[p].su=s[p].su+v;
s[p].pf=(s[p].su*s[p].su);
return;
}
add(lc,l,r,v);add(rc,l,r,v);
pushup(p);
}
int querys(int p,int l,int r){
if(s[p].l>r||s[p].r<l)return 0;
if(s[p].l>=l&&s[p].r<=r)return s[p].su;
return (querys(lc,l,r)+querys(rc,l,r));
}
int queryp(int p,int l,int r){
if(s[p].l>r||s[p].r<l)return 0;
if(s[p].l>=l&&s[p].r<=r)return s[p].pf;
return (queryp(lc,l,r)+queryp(rc,l,r));
}
signed main(){
scanf("%lld%lld",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
int c,l,r,dd;
scanf("%lld%lld%lld",&c,&l,&r);
if(c==1)scanf("%lld",&dd),add(1,l,r,dd);
else if(c==2){
double a=querys(1,l,r);
printf("%.4lf\n",1.0*a/(r-l+1));
}
else {
int a=querys(1,l,r),b=queryp(1,l,r);
double biv=1.0*b/(r-l+1)-1.0*a*a/((r-l+1)*(r-l+1));
printf("%.4lf\n",biv);
}
}
return 0;
}