#include<bits/stdc++.h>
using namespace std;
const int N=(int)1e5+10;
int n,m,L,R;
double a[N];
struct node{
int l,r;
double val1,val2,lazy;
}t[N*4];
void pushup(int u){
t[u].val1=t[u*2].val1+t[u*2+1].val1;
t[u].val2=t[u*2].val2+t[u*2+1].val2;
}
void build(int u,int l,int r){
t[u].l=l;
t[u].r=r;
if(l==r){
t[u].val1=a[l];
t[u].val2=a[l]*a[l];
return;
}
int mid=(l+r)/2;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
pushup(u);
}
void pushdown(int u){
t[u*2].lazy+=t[u].lazy;
t[u*2+1].lazy+=t[u].lazy;
t[u*2].val2+=t[u].lazy*t[u].lazy+2*t[u*2].val1*t[u].lazy;
t[u*2+1].val2+=t[u].lazy*t[u].lazy+2*t[u*2+1].val1*t[u].lazy;
t[u*2].val1+=t[u].lazy*(t[u*2].r-t[u*2].l+1);
t[u*2+1].val1+=t[u].lazy*(t[u*2+1].r-t[u*2+1].l+1);
t[u].lazy=0;
}
void modify(int u,int l,int r,double x){
if(l<=t[u].l&&t[u].r<=r){
t[u].lazy+=x;
t[u].val2+=x*x+2*t[u].val1*x;
t[u].val1+=x*(t[u].r-t[u].l+1);
return;
}
int mid=(t[u].l+t[u].r)/2;
pushdown(u);
if(l<=mid) modify(u*2,l,r,x);
if(mid<r) modify(u*2+1,l,r,x);
pushup(u);
}
double query1(int u,int l,int r){
if(t[u].l>R||t[u].r<L) return 0;
if(t[u].l>=L&&t[u].r<=R) return t[u].val1;
pushdown(u);
return query1(u*2,L,R)+query1(u*2+1,L,R);
}
double query2(int u,int l,int r){
if(t[u].l>R||t[u].r<L) return 0;
if(t[u].l>=L&&t[u].r<=R) return t[u].val2;
pushdown(u);
return query2(u*2,L,R)+query2(u*2+1,L,R);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
}
build(1,1,n);
while(m--){
int op,x,y;
double k;
scanf("%d",&op);
if(op==1){
scanf("%d%d%lf",&x,&y,&k);
modify(1,x,y,k);
}else if(op==2){
scanf("%d%d",&x,&y);
L=x;R=y;
printf("%.4f\n",query1(1,1,n)/(y-x+1));
}else{
scanf("%d%d",&x,&y);
L=x,R=y;
double p=1.0*query1(1,1,n)/(y-x+1);
double q=(query2(1,1,n)+p*p*(y-x+1)-2*p*query1(1,1,n))/n;
printf("%.4f\n",q);
}
}
return 0;
}