给出
n
≤
1
e
5
n\leq1e5
n≤1e5个数,然后每次操作选择两个不相交也不重合的区间
l
1
≤
r
1
<
l
2
≤
r
2
l_1\leq r_1<l_2\leq r_2
l1≤r1<l2≤r2,随机从里面各选择一个数交换。另外要求查询区间
l
1
≤
r
1
l_1\leq r_1
l1≤r1的期望和。
用线段树维护期望和,初始状态期望和就是数值之和。考虑区间
[
l
1
,
r
1
]
[l_1,r_1]
[l1,r1]中单个数字在一次修改中的变化,有
r
1
−
l
1
r
1
−
l
1
+
1
\frac{r_1-l_1}{r_1-l_1+1}
r1−l1+1r1−l1的概率仍然是本身,还有
1
r
1
−
l
1
+
1
\frac{1}{r_1-l_1+1}
r1−l1+11的概率变成
∑
i
=
l
2
r
2
a
i
r
2
−
l
2
+
1
\frac{\sum_{i=l_2}^{r_2}a_{i}}{r_2-l_2+1}
r2−l2+1∑i=l2r2ai,而每个数都是这样,所以就变成区间乘
r
1
−
l
1
r
1
−
l
1
+
1
\frac{r_1-l_1}{r_1-l_1+1}
r1−l1+1r1−l1,再区间加
∑
i
=
l
2
r
2
a
i
r
2
−
l
2
+
1
\frac{\sum_{i=l_2}^{r_2}a_{i}}{r_2-l_2+1}
r2−l2+1∑i=l2r2ai。另外一个区间也同理。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=1e5+7;
double a[N];
const double eps=1e-6;
double sum[N<<2],add[N<<2],mul[N<<2];
void pushup(int rt) {
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int l,int mid,int r) {
if(abs(mul[rt]-1.0)>eps) {
sum[rt<<1]*=mul[rt];
sum[rt<<1|1]*=mul[rt];
mul[rt<<1]*=mul[rt];
mul[rt<<1|1]*=mul[rt];
add[rt<<1]*=mul[rt];
add[rt<<1|1]*mul[rt];
mul[rt]=1;
}
if(abs(add[rt])>eps) {
sum[rt<<1]+=add[rt]*(mid-l+1);
sum[rt<<1|1]+=add[rt]*(r-mid);
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt]=0;
}
}
void build(int rt,int l,int r) {
mul[rt]=1;add[rt]=0;
if(l==r) { mul[rt]=1;add[rt]=0;sum[rt]=a[l];return;}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void ADD(int rt,int l,int r,int L,int R,double x) {
if(R<l||L>r) return;
if(L<=l&&r<=R) {
sum[rt]+=x*(r-l+1);
add[rt]+=x;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,mid,r);
ADD(rt<<1,l,mid,L,R,x);
ADD(rt<<1|1,mid+1,r,L,R,x);
pushup(rt);
}
void MUL(int rt,int l,int r,int L,int R,double x) {
if(R<l||L>r) return;
if(L<=l&&r<=R) {
sum[rt]*=x;
mul[rt]*=x;
add[rt]*=x;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,mid,r);
MUL(rt<<1,l,mid,L,R,x);
MUL(rt<<1|1,mid+1,r,L,R,x);
pushup(rt);
}
double query(int rt,int l,int r,int L,int R) {
if(L>r||R<l) return 0;
if(L<=l&&r<=R) return sum[rt];
int mid=(l+r)>>1;
pushdown(rt,l,mid,r);
return query(rt<<1,l,mid,L,R)+query(rt<<1|1,mid+1,r,L,R);
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
build(1,1,n);
while(m--) {
int opt;
int l1,r1,l2,r2;
scanf("%d",&opt);
if(opt==1) {
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
double A=query(1,1,n,l1,r1);
double B=query(1,1,n,l2,r2);
MUL(1,1,n,l1,r1,1.0*(r1-l1)/(r1-l1+1));
MUL(1,1,n,l2,r2,1.0*(r2-l2)/(r2-l2+1));
ADD(1,1,n,l1,r1,B/((r1-l1+1)*(r2-l2+1)));
ADD(1,1,n,l2,r2,A/((r2-l2+1)*(r1-l1+1)));
}
if(opt==2) {
scanf("%d%d",&l1,&r1);
printf("%.10lf\n",query(1,1,n,l1,r1));
}
}
return 0;
}