/*
从区间[l1,r1]取出一个数,这个数的期望值为 e1=(sum[r1]-sum[l1-1])/(r1-l1+1)
同理从区间[l2,r2]里取出一个数,这个数期望为 e2=(sum[r2]-sum[l2-1])/(r2-l2+1)
根据期望线性性,[l1,r1]里每个数被选中的概率是1/len1
所以一次交换后该区间的a[i] -> (len1-1)/len1*a[i]+1/len1*e2
同理[l2,r2]里的 a[i] -> (len2-1)/len2*a[i]+1/len2*e1
用一个线段树来维护sum,两个tag:mul和add
*/
#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n,a[N],q;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
double sum[N<<2],mul[N<<2],add[N<<2];
void pushdown(int l,int r,int rt){
int m=l+r>>1;
sum[rt<<1]*=mul[rt];sum[rt<<1]+=(m-l+1)*add[rt];
sum[rt<<1|1]*=mul[rt];sum[rt<<1|1]+=(r-m)*add[rt];
mul[rt<<1]*=mul[rt];
mul[rt<<1|1]*=mul[rt];
add[rt<<1]*=mul[rt];add[rt<<1]+=add[rt];
add[rt<<1|1]*=mul[rt];add[rt<<1|1]+=add[rt];
mul[rt]=1;add[rt]=0;
}
void build(int l,int r,int rt){
mul[rt]=1;add[rt]=0;
if(l==r){sum[rt]=a[l];return;}
int m=l+r>>1;
build(lson);build(rson);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int L,int R,double MUL,double ADD,int l,int r,int rt){
if(L<=l && R>=r){
sum[rt]*=MUL;sum[rt]+=ADD*(r-l+1);
mul[rt]*=MUL;
add[rt]*=MUL;add[rt]+=ADD;
return;
}
pushdown(l,r,rt);
int m=l+r>>1;
if(L<=m)update(L,R,MUL,ADD,lson);
if(R>m)update(L,R,MUL,ADD,rson);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
double query(int L,int R,int l,int r,int rt){
if(L<=l && R>=r)return sum[rt];
pushdown(l,r,rt);
int m=l+r>>1;
double res=0;
if(L<=m)res+=query(L,R,lson);
if(R>m)res+=query(L,R,rson);
return res;
}
int main(){
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
build(1,n,1);
while(q--){
int op,l1,l2,r1,r2,len1,len2;
cin>>op;
if(op==2){
scanf("%d%d",&l1,&r1);
cout<<query(l1,r1,1,n,1)<<'\n';
}
else {
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
len1=r1-l1+1;
len2=r2-l2+1;
double sum1=query(l1,r1,1,n,1);
double sum2=query(l2,r2,1,n,1);
double e1=sum1/len1;
double e2=sum2/len2;
double mul1=1.0*(len1-1)/len1;
double mul2=1.0*(len2-1)/len2;
double add1=1.0/len1*e2;
double add2=1.0/len2*e1;
update(l1,r1,mul1,add1,1,n,1);
update(l2,r2,mul2,add2,1,n,1);
}
}
}