#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <complex>
#include <stack>
#define LL long long int
#define dob long double
#define ls (x<<1)
#define rs (x<<1|1)
using namespace std;
const int N = 400010;
struct Tree{
dob x,y,xx,xy;
Tree operator +(const Tree &t){
return (Tree){x+t.x,y+t.y,xx+t.xx,xy+t.xy};
}
}Tr[N*4];
int n,m,lazy_vis[N];
dob X[N/4],Y[N/4],lazy_add1[N],lazy_add2[N],lazy_set1[N],lazy_set2[N];
inline int gi(){
int x=0,res=1;char ch=getchar();
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)res*=-1;ch=getchar();}
while(ch<=‘9‘&&ch>=‘0‘)x=x*10+ch-48,ch=getchar();
return x*res;
}
inline void build(int x,int l,int r){
if(l==r){
Tr[x]=(Tree){X[l],Y[l],1.0*X[l]*X[l],1.0*X[l]*Y[l]};
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
Tr[x]=Tr[ls]+Tr[rs];
}
inline dob calc(dob l,dob r){
return 0.5*(l+r)*(r-l+1);
}
inline dob calcpow(dob l,dob r){
l-=1;
dob p1=1.0*(r)*(r+1)*(2*r+1)/6.0;
dob p2=1.0*(l)*(l+1)*(2*l+1)/6.0;
return p1-p2;
}
inline void down(int x,int l,int r){
int mid=(l+r)>>1,sl=mid-l+1,sr=r-mid;
if(lazy_vis[x]){
lazy_add1[ls]=lazy_add1[rs]=lazy_add2[ls]=lazy_add2[rs]=0;
lazy_vis[ls]=lazy_vis[rs]=1;
dob S=lazy_set1[x],T=lazy_set2[x];
lazy_set1[ls]=lazy_set1[rs]=lazy_set1[x];
lazy_set2[ls]=lazy_set2[rs]=lazy_set2[x];
Tr[ls].xx=1.0*sl*S*S+2.0*S*calc(l,mid)+calcpow(l,mid);
Tr[rs].xx=1.0*sr*S*S+2.0*S*calc(mid+1,r)+calcpow(mid+1,r);
Tr[ls].xy=1.0*sl*S*T+1.0*(S+T)*calc(l,mid)+calcpow(l,mid);
Tr[rs].xy=1.0*sr*S*T+1.0*(S+T)*calc(mid+1,r)+calcpow(mid+1,r);
Tr[ls].x=1.0*sl*S+calc(l,mid);Tr[rs].x=1.0*sr*S+calc(mid+1,r);
Tr[ls].y=1.0*sl*T+calc(l,mid);Tr[rs].y=1.0*sr*T+calc(mid+1,r);
lazy_vis[x]=0;
}
if(lazy_add1[x] || lazy_add2[x]){
dob S=lazy_add1[x],T=lazy_add2[x];
lazy_add1[ls]+=S;lazy_add1[rs]+=S;
lazy_add2[ls]+=T;lazy_add2[rs]+=T;
Tr[ls].xx+=2.0*Tr[ls].x*S+1.0*sl*S*S;
Tr[rs].xx+=2.0*Tr[rs].x*S+1.0*sr*S*S;
Tr[ls].xy+=1.0*Tr[ls].x*T+1.0*Tr[ls].y*S+1.0*sl*S*T;
Tr[rs].xy+=1.0*Tr[rs].x*T+1.0*Tr[rs].y*S+1.0*sr*S*T;
Tr[ls].x+=1.0*sl*S;Tr[rs].x+=1.0*sr*S;
Tr[ls].y+=1.0*sl*T;Tr[rs].y+=1.0*sr*T;
lazy_add1[x]=lazy_add2[x]=0;
}
}
inline Tree query_1(int x,int l,int r,int xl,int xr){
if(xl<=l && r<=xr)return Tr[x];
down(x,l,r);int mid=(l+r)>>1;
if(xr<=mid)return query_1(ls,l,mid,xl,xr);
else if(xl>mid)return query_1(rs,mid+1,r,xl,xr);
return query_1(ls,l,mid,xl,mid)+query_1(rs,mid+1,r,mid+1,xr);
}
inline void update_2(int x,int l,int r,int xl,int xr,dob S,dob T){
if(xl<=l && r<=xr){
lazy_add1[x]+=S;lazy_add2[x]+=T;
Tr[x].xx+=2.0*Tr[x].x*S+1.0*(r-l+1)*S*S;
Tr[x].xy+=1.0*Tr[x].x*T+1.0*Tr[x].y*S+1.0*(r-l+1)*S*T;
Tr[x].x+=1.0*(r-l+1)*S;Tr[x].y+=1.0*(r-l+1)*T;
return;
}
down(x,l,r);int mid=(l+r)>>1;
if(xr<=mid)update_2(ls,l,mid,xl,xr,S,T);
else if(xl>mid)update_2(rs,mid+1,r,xl,xr,S,T);
else update_2(ls,l,mid,xl,mid,S,T),update_2(rs,mid+1,r,mid+1,xr,S,T);
Tr[x]=Tr[ls]+Tr[rs];
}
inline void update_3(int x,int l,int r,int xl,int xr,dob S,dob T){
if(xl<=l && r<=xr){
lazy_add1[x]=lazy_add2[x]=0;
lazy_vis[x]=1;lazy_set1[x]=S;lazy_set2[x]=T;
Tr[x].xx=1.0*(r-l+1)*S*S+2.0*S*calc(1.0*l,1.0*r)+calcpow(1.0*l,1.0*r);
Tr[x].xy=1.0*(r-l+1)*S*T+1.0*(S+T)*calc(l,r)+calcpow(l,r);
Tr[x].x=1.0*(r-l+1)*S+calc(l,r);Tr[x].y=1.0*(r-l+1)*T+calc(l,r);
return;
}
down(x,l,r);int mid=(l+r)>>1;
if(xr<=mid)update_3(ls,l,mid,xl,xr,S,T);
else if(xl>mid)update_3(rs,mid+1,r,xl,xr,S,T);
else update_3(ls,l,mid,xl,mid,S,T),update_3(rs,mid+1,r,mid+1,xr,S,T);
Tr[x]=Tr[ls]+Tr[rs];
}
int main()
{
/*freopen(".in","r",stdin);
freopen(".out","w",stdout);*/
n=gi();m=gi();
for(int i=1;i<=n;++i)X[i]=gi();
for(int i=1;i<=n;++i)Y[i]=gi();
build(1,1,n);
for(int i=1;i<=m;++i){
int type=gi();
if(type==1){
int l=gi(),r=gi();
Tree ans=query_1(1,1,n,l,r);
dob fz=ans.xy-ans.x*ans.y/(r-l+1);
dob fm=ans.xx-ans.x*ans.x/(r-l+1);
printf("%.10Lf\n",fz/fm);
}
if(type==2){
int l=gi(),r=gi(),S=gi(),T=gi();
update_2(1,1,n,l,r,1.0*S,1.0*T);
}
if(type==3){
int l=gi(),r=gi(),S=gi(),T=gi();
update_3(1,1,n,l,r,1.0*S,1.0*T);
}
}
/*fclose(stdin);
fclose(stdout);*/
return 0;
}