如果时暴力做的话:
对l1,r1区间内的数,每个数有1/(r1-l1+1)的概率被替换,被替换成的数的期望为sum(l2,r2)/(r2-l2+1)
所以l1,r1区间内一个数 a[x]=1/(r1-l1+1)*sum(l2,r2)/(r2-l2+1) +(r1-l1)/(r1-l1+1) * a[x];
化简为: a[x]= a[x]*k + b;
k,b是常数。
然后用线段树维护搞搞就行
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 LL;
//typedef unsigned long long ull;
//#define F first
//#define S second
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
const ld PI=acos(-1);
const ld eps=1e-9;
//unordered_map<int,int>mp;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)] //m是矩阵的列数
//pop_back()
const int seed=131;
const int M = 1e5+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
double a[M];
double sm[M<<2];//维护区间和
double mul[M<<2];//乘法标记
double add[M<<2];//加法标记
void bd(int o,int l,int r)
{
mul[o]=1,add[o]=0;
if(l==r)
{
mul[o]=1;
add[o]=0;
sm[o]=a[l];
return ;
}
int m=(l+r)/2;
bd(ls,l,m);
bd(rs,m+1,r);
sm[o]=sm[ls]+sm[rs];
}
void pd(int o,int l,int r)
{
int m=(l+r)/2;
// if(mul[o]==1&&add[o]==0)
{
mul[ls]*=mul[o],mul[rs]*=mul[o];
add[ls]*=mul[o],add[rs]*=mul[o];
add[ls]+=add[o],add[rs]+=add[o];
sm[ls]=sm[ls]*mul[o]+add[o]*(m-l+1);
sm[rs]=sm[rs]*mul[o]+add[o]*(r-m);
mul[o]=1;add[o]=0;
}
}
void up(int o,int l,int r,int x,int y,double k,double b)//x-y区间内先乘k再加b
{
if(x<=l&&r<=y)
{
mul[o]*=k,add[o]*=k,add[o]+=b;
sm[o]=sm[o]*k+b*(r-l+1);
return ;
}
pd(o,l,r);
int m=(l+r)/2;
if(x<=m)up(ls,l,m,x,y,k,b);
if(y>m)up(rs,m+1,r,x,y,k,b);
sm[o]=sm[ls]+sm[rs];
}
double qu(int o,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return sm[o];
}
int m=(l+r)/2;
pd(o,l,r);
double ans=0;
if(x<=m)ans+=qu(ls,l,m,x,y);
if(y>m)ans+=qu(rs,m+1,r,x,y);
return ans;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
bd(1,1,n);
while(q--)
{
// cout<<"okkk"<<endl;
int opt,l1,r1,l2,r2;
double sm1=0,sm2=0,k,b;
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
sm1=qu(1,1,n,l1,r1);sm2=qu(1,1,n,l2,r2);
k=1.0*(r1-l1)/(r1-l1+1);
b=sm2/(r2-l2+1);
b/=(r1-l1+1);
up(1,1,n,l1,r1,k,b);//l1,r1区间的数先乘k再加b
// cout<<k<<" "<<b;
k=1.0*(r2-l2)/(r2-l2+1);b=sm1/(r1-l1+1);
b/=(r2-l2+1);
up(1,1,n,l2,r2,k,b);
// cout<<" ----"<<k<<" "<<b<<endl;
}
else
{
scanf("%d%d",&l1,&r1);
double tp=qu(1,1,n,l1,r1);
printf("%.7f\n",tp);
}
}
return 0;
}