题目链接:http://codeforces.com/contest/895/problem/E
期望好像不太会哦?考虑第一种操作,在[l,r]区间当中,每一个点留在原地的概率为(r-l)/(r-l+1),然后被换过来的数期望为另一个区间的平均值然后乘上1/(r-l+1),所以对于1操作,直接乘(r-l)/(r-l+1)然后加上另一个区间的平均值乘1/(r-l+1),维护一个支持乘法和加法的线段树就好。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
const double eps=1e-6;
int a[MAXN];
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
struct node
{
double val,mul,add;
}sum[MAXN<<2];
int sgn(double x)
{
if(fabs(x)<eps) return 0;
else if(x>eps) return 1;
else if(x<-eps) return -1;
}
inline void push_up(int rt)
{
sum[rt].val=sum[rt<<1].val+sum[rt<<1|1].val;
}
inline void push_down(int l,int r,int rt)
{
if(sgn(sum[rt].mul-1))
{
sum[rt<<1].val*=sum[rt].mul;
sum[rt<<1].mul*=sum[rt].mul;
sum[rt<<1].add*=sum[rt].mul;
sum[rt<<1|1].val*=sum[rt].mul;
sum[rt<<1|1].mul*=sum[rt].mul;
sum[rt<<1|1].add*=sum[rt].mul;
sum[rt].mul=1;
}
if(sgn(sum[rt].add))
{
int mid=(l+r)>>1;
sum[rt<<1].val+=sum[rt].add*(mid-l+1);
sum[rt<<1].add+=sum[rt].add;
sum[rt<<1|1].val+=sum[rt].add*(r-mid);
sum[rt<<1|1].add+=sum[rt].add;
sum[rt].add=0;
}
}
void build(int l,int r,int rt)
{
sum[rt].mul=1;sum[rt].add=0;
if(l==r)
{
sum[rt].val=a[l];
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
void update_mul(int L,int R,double val,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
sum[rt].mul*=val;
sum[rt].val*=val;
sum[rt].add*=val;
return ;
}
int mid=(l+r)>>1;
push_down(root);
if(L<=mid)
{
update_mul(L,R,val,lson);
}
if(mid<R)
{
update_mul(L,R,val,rson);
}
push_up(rt);
}
void update_add(int L,int R,double val,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
sum[rt].add+=val;
sum[rt].val+=(r-l+1)*val;
return ;
}
int mid=(l+r)>>1;
push_down(root);
if(L<=mid)
{
update_add(L,R,val,lson);
}
if(mid<R)
{
update_add(L,R,val,rson);
}
push_up(rt);
}
double query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return sum[rt].val;
}
int mid=(l+r)>>1;
double ret=0;
push_down(root);
if(L<=mid)
{
ret+=query(L,R,lson);
}
if(mid<R)
{
ret+=query(L,R,rson);
}
return ret;
}
}se;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
se.build(1,n,1);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int l1,r1,l2,r2;
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
double x1=se.query(l1,r1,1,n,1)/(r1-l1+1)/(r2-l2+1);
double x2=se.query(l2,r2,1,n,1)/(r2-l2+1)/(r1-l1+1);
se.update_mul(l1,r1,1.0*(r1-l1)/(r1-l1+1),1,n,1);
se.update_mul(l2,r2,1.0*(r2-l2)/(r2-l2+1),1,n,1);
se.update_add(l1,r1,x2,1,n,1);
se.update_add(l2,r2,x1,1,n,1);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
printf("%.10lf\n",se.query(l,r,1,n,1));
}
}
return 0;
}