#include<iostream>
using namespace std;
const int N=1e5+5;
struct node
{
int l,r;
double data,dt,add;
}t[4*N];
int n,q,op,l,r;
double k;
double a[N];
void pushup(int x)
{
t[x].data=t[2*x].data+t[2*x+1].data;
t[x].dt=t[2*x].dt+t[2*x+1].dt;
}
void build(int x,int l,int r)
{
t[x].l=l,t[x].r=r;
if(l==r)
{
t[x].data=a[l];
t[x].dt=a[l]*a[r];
t[x].add=0;
return;
}
int mid=(l+r)/2;
build(2*x,l,mid);
build(2*x+1,mid+1,r);
pushup(x);
}
void pushdown(int x)
{
t[2*x].dt+=t[x].add*t[x].add*(t[2*x].r-t[2*x].l+1)+2*t[2*x].data*t[x].add;
t[2*x+1].dt+=t[x].add*t[x].add*(t[2*x+1].r-t[2*x+1].l+1)+2*t[2*x+1].data*t[x].add;
t[2*x].data+=t[x].add*(t[2*x].r-t[2*x].l+1);
t[2*x+1].data+=t[x].add*(t[2*x+1].r-t[2*x+1].l+1);
t[2*x].add+=t[x].add;
t[2*x+1].add+=t[x].add;
t[x].add=0;
}
void change(int x,int l,int r,double k)
{
if(l<=t[x].l&&t[x].r<=r)
{
t[x].dt+=k*k*(t[x].r-t[x].l+1)+2*t[x].data*k;
t[x].data+=k*(t[x].r-t[x].l+1);
t[x].add+=k;
return;
}
pushdown(x);
int mid=(t[x].l+t[x].r)/2;
if(l<=mid) change(2*x,l,r,k);
if(r>mid) change(2*x+1,l,r,k);
pushup(x);
}
double query1(int x,int l,int r)
{
if(l<=t[x].l&&t[x].r<=r)
{
return t[x].data;
}
pushdown(x);
double sum=0;
int mid=(t[x].l+t[x].r)/2;
if(l<=mid) sum+=query1(2*x,l,r);
if(r>mid) sum+=query1(2*x+1,l,r);
return sum;
}
double query2(int x,int l,int r)
{
if(l<=t[x].l&&t[x].r<=r)
{
return t[x].dt;
}
pushdown(x);
double sum=0;
int mid=(t[x].l+t[x].r)/2;
if(l<=mid) sum+=query2(2*x,l,r);
if(r>mid) sum+=query2(2*x+1,l,r);
return sum;
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(q--)
{
cin>>op>>l>>r;
if(op==1)
{
cin>>k;
change(1,l,r,k);
}
double ba=query1(1,l,r)*1.0/(r-l+1);
if(op==2) printf("%.4lf\n",ba);
if(op==3)
{
printf("%.4lf\n",-ba*ba+query2(1,l,r)*1.0/n);
}
}
return 0;
}