/*
将原式化简,会发现最后只需要维护四个东西,分别是:Σx,Σy,Σx*y,Σx*x。
区间加的时候x和y都很容易,
Σx*y=Σ(x+S)*(y+T)=Σx*y+S*Σy+T*Σx+len*S*T
Σx*x=Σ(x+S)*(x+S)=Σx*x+2*S*Σx+len*S*S
区间修改的时候
Σ(i+S)*(i+T)=Σi*i+(S+T)*Σi+len*S*T
Σ(i+S)*(i+S)=Σi*i+2*S*Σi+len*S*S
注意区间加和区间修改的先后顺序,有区间修改时应该先修改在进行区间加;
而有区间加的时候,可以直接进行区间修改。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 400010
#define inf 1000000000
using namespace std;
const double eps=1e-8;
int n,m,X[N],Y[N];
double Xs[N],Ys[N],Sq[N],Mul[N],Xdlt[N],Ydlt[N];
double Is[N],Is2[N],Xcov[N],Ycov[N];
struct node{
double sx,sy,sq,ml;
node(){sx=sy=sq=ml=0;}
};
void update(int i){
Xs[i]=Xs[i<<1]+Xs[(i<<1)+1];
Ys[i]=Ys[i<<1]+Ys[(i<<1)+1];
Sq[i]=Sq[i<<1]+Sq[(i<<1)+1];
Mul[i]=Mul[i<<1]+Mul[(i<<1)+1];
}
void Cov(int i,int l,int r,double cx,double cy){
double len=(r-l+1);
Xdlt[i]=Ydlt[i]=0;
Xcov[i]=cx;Ycov[i]=cy;
Sq[i]=cx*cx*len+2*cx*Is[i]+Is2[i];
Mul[i]=cx*cy*len+(cx+cy)*Is[i]+Is2[i];
Xs[i]=cx*len+Is[i];Ys[i]=cy*len+Is[i];
}
void Add(int i,int l,int r,double dx,double dy){
double len=r-l+1;
if (Xcov[i]!=inf||Ycov[i]!=inf){
Cov(i,l,r,Xcov[i]+dx,Ycov[i]+dy);
return;
}
Xdlt[i]+=dx;Ydlt[i]+=dy;
Sq[i]+=dx*dx*len+2*dx*Xs[i];
Mul[i]+=dx*Ys[i]+dy*Xs[i]+dx*dy*len;
Xs[i]+=dx*len;Ys[i]+=dy*len;
}
void pushdown(int i,int l,int r){
if (Xdlt[i]!=0||Ydlt[i]!=0){
int mid=(l+r)>>1;
Add(i<<1,l,mid,Xdlt[i],Ydlt[i]);
Add((i<<1)+1,mid+1,r,Xdlt[i],Ydlt[i]);
Xdlt[i]=Ydlt[i]=0;
}
if (Xcov[i]!=inf||Ycov[i]!=inf){
int mid=(l+r)>>1;
Cov(i<<1,l,mid,Xcov[i],Ycov[i]);
Cov((i<<1)+1,mid+1,r,Xcov[i],Ycov[i]);
Xcov[i]=Ycov[i]=inf;
}
}
void build(int i,int l,int r){
Xcov[i]=Ycov[i]=inf;
if (l==r){
double xx=X[l],yy=Y[l];
Xs[i]=xx;Ys[i]=yy;
Sq[i]=xx*xx;Mul[i]=xx*yy;
Is[i]=l;Is2[i]=(double)l*(double)l;
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build((i<<1)+1,mid+1,r);
update(i);
Is[i]=Is[i<<1]+Is[(i<<1)+1];
Is2[i]=Is2[i<<1]+Is2[(i<<1)+1];
}
void ask(int i,int l,int r,int x,int y,node &ans){
if (x<=l&&y>=r){
ans.sx+=Xs[i];ans.sy+=Ys[i];
ans.sq+=Sq[i];ans.ml+=Mul[i];
return;
}
int mid=(l+r)>>1;
pushdown(i,l,r);
if (x<=mid) ask(i<<1,l,mid,x,y,ans);
if (y>mid) ask((i<<1)+1,mid+1,r,x,y,ans);
}
double Getans(int l,int r){
node tmp;
double avex,avey,len=r-l+1,up,down;
up=down=0;ask(1,1,n,l,r,tmp);
avex=tmp.sx/len;avey=tmp.sy/len;
down=tmp.sq-2*avex*tmp.sx+avex*avex*len;
up=tmp.ml-avey*tmp.sx-avex*tmp.sy+avex*avey*len;
return up/down+eps;
}
void add(int i,int l,int r,int x,int y,double s,double t){
if (x<=l&&y>=r){Add(i,l,r,s,t);return;}
int mid=(l+r)>>1;
pushdown(i,l,r);
if (x<=mid) add(i<<1,l,mid,x,y,s,t);
if (y>mid) add((i<<1)+1,mid+1,r,x,y,s,t);
update(i);
}
void cover(int i,int l,int r,int x,int y,double s,double t){
if (x<=l&&y>=r){Cov(i,l,r,s,t);return;}
int mid=(l+r)>>1;
pushdown(i,l,r);
if (x<=mid) cover(i<<1,l,mid,x,y,s,t);
if (y>mid) cover((i<<1)+1,mid+1,r,x,y,s,t);
update(i);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&X[i]);
for (int i=1;i<=n;i++) scanf("%d",&Y[i]);
build(1,1,n);
for (int i=1;i<=m;i++){
int type,l,r,s,t;
scanf("%d%d%d",&type,&l,&r);
if (type==1) printf("%.10lf\n",Getans(l,r));
if (type==2){
scanf("%d%d",&s,&t);
add(1,1,n,l,r,s,t);
}
if (type==3){
scanf("%d%d",&s,&t);
cover(1,1,n,l,r,s,t);
}
}
return 0;
}