/* 从区间[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)<<' '; } 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); } } }