#include"iostream"
#include"algorithm"
using namespace std;
const int N=int (1e5)+7;
struct tree
{
int l,r;
int siz;
double sum,sum2;
double tag;
}tr[N<<2];
void update(int x){
tr[x].siz=tr[x<<1].siz+tr[x<<1|1].siz;
tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
tr[x].sum2=tr[x<<1].sum2+tr[x<<1|1].sum2;
}
void updown(int x){
if(tr[x].tag*1000==0) return;
tr[x<<1].sum2+=2.0000*tr[x].tag*tr[x<<1].sum+tr[x<<1].siz*1.0000*tr[x].tag*tr[x].tag;
tr[x<<1].sum+=tr[x].tag*1.0*tr[x<<1].siz;
tr[x<<1].tag+=tr[x].tag;
tr[x<<1|1].sum2+=2.0000*tr[x].tag*tr[x<<1|1].sum+tr[x<<1|1].siz*1.0000*tr[x].tag*tr[x].tag;
tr[x<<1|1].sum+=tr[x].tag*tr[x<<1|1].siz*1.0000;
tr[x<<1|1].tag+=tr[x].tag;
tr[x].tag=0.0000;
}
void build(int x,int l,int r){
tr[x].l=l,tr[x].r=r;
if(l==r){
tr[x].siz=1;
scanf("%lf",&tr[x].sum);
tr[x].sum2=tr[x].sum*tr[x].sum*1.0000;
return;
}
int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
update(x);
}
void add(int x,int l,int r,double d){
if(l<=tr[x].l&&tr[x].r<=r){
tr[x].sum2+=2.0000*d*tr[x].sum+(r-l+1)*d*1.0000*d*1.0000;
tr[x].sum+=(1.0000*d*tr[x].siz*1.0000);
tr[x].tag+=d;
return;
}
int mid=tr[x].l+tr[x].r>>1;
updown(x);
if(l<=mid) add(x<<1,l,r,d);
if(r>mid) add(x<<1|1,l,r,d);
update(x);
}
tree ask(int x,int l,int r){
if(tr[x].l>=l&&tr[x].r<=r){
return tr[x];
}
int mid=tr[x].l+tr[x].r>>1;
updown(x);
if(r<=mid) return ask(x<<1,l,r);
else if(l>mid) return ask(x<<1|1,l,r);
else{
tree a=ask(x<<1,l,r),b=ask(x<<1|1,l,r),t;
t.siz=a.siz+b.siz;
t.sum=a.sum+b.sum;
t.sum2=a.sum2+b.sum2;
return t;
}
}
int main(){
int n,m; scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int op,x,y; scanf("%d%d%d",&op,&x,&y);
if(op==1){
double d; scanf("%lf",&d);
add(1,x,y,d);
}else if(op==2){
tree t=ask(1,x,y);
printf("%.4lf\n",t.sum*1.0000/t.siz*1.0000);
}else{
tree t=ask(1,x,y);
double sum2=t.sum2;
double sum=t.sum;
double siz=t.siz;
printf("%.4lf\n",t.sum2*1.0000/t.siz*1.0000-(t.sum/t.siz*1.0000)*(t.sum/t.siz*1.0000));
}
}
}