[CF895E]Eyes Closed

luogu

description

一个序列\(a_i\),支持一下两种操作。
\(1\ \ l_1\ \ r_1\ \ l_2\ \ r_2\): 随机交换区间\([l_1,r_1]\)\([l_2,r_2]\)中的两个值。
\(2\ \ l\ \ r\):查询\(\sum_{i=l}^ra_i\)的期望。

sol

设两个交换区间的和分别是\(s_1,s_2\),长度分别是\(len_1,len_2\)
考虑区间\([l_1,r_1]\)中的一个元素\(x\),在交换后它的期望值会变为:
\(\frac{len_1-1}{len_1}x+\frac{1}{len_1}\times\frac{s_2}{len_2}\)
区间\([l_2,r_2]\)中的数同理,会变成:
\(\frac{len_2-1}{len_2}x+\frac{1}{len_2}\times\frac{s_1}{len_1}\)
所以线段树支持区间加区间乘区间求和即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
	int x=0,w=1;char ch=getchar();
	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if (ch=='-') w=0,ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return w?x:-x;
}
const int N = 2e5+5;
int n,m;double sum[N<<2],pls[N<<2],mul[N<<2];
void build(int x,int l,int r){
	if (l==r) {sum[x]=gi();return;}
	int mid=l+r>>1;mul[x]=1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
void cover_pls(int x,int l,int r,double v){
	sum[x]+=v*(r-l+1);pls[x]+=v;
}
void cover_mul(int x,double v){
	sum[x]*=v;mul[x]*=v;pls[x]*=v;
}
void pushdown(int x,int l,int r){
	int mid=l+r>>1;
	cover_mul(x<<1,mul[x]),cover_mul(x<<1|1,mul[x]);
	cover_pls(x<<1,l,mid,pls[x]),cover_pls(x<<1|1,mid+1,r,pls[x]);
	pls[x]=0;mul[x]=1;
}
void modify_pls(int x,int l,int r,int ql,int qr,double v){
	if (l>=ql&&r<=qr) {cover_pls(x,l,r,v);return;}
	pushdown(x,l,r);int mid=l+r>>1;
	if (ql<=mid) modify_pls(x<<1,l,mid,ql,qr,v);
	if (qr>mid) modify_pls(x<<1|1,mid+1,r,ql,qr,v);
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
void modify_mul(int x,int l,int r,int ql,int qr,double v){
	if (l>=ql&&r<=qr) {cover_mul(x,v);return;}
	pushdown(x,l,r);int mid=l+r>>1;
	if (ql<=mid) modify_mul(x<<1,l,mid,ql,qr,v);
	if (qr>mid) modify_mul(x<<1|1,mid+1,r,ql,qr,v);
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
double query(int x,int l,int r,int ql,int qr){
	if (l>=ql&&r<=qr) return sum[x];
	pushdown(x,l,r);int mid=l+r>>1;double res=0;
	if (ql<=mid) res+=query(x<<1,l,mid,ql,qr);
	if (qr>mid) res+=query(x<<1|1,mid+1,r,ql,qr);
	return res;
}
int main(){
	n=gi();m=gi();build(1,1,n);
	while (m--){
		int opt=gi();
		if (opt==1){
			int a=gi(),b=gi(),c=gi(),d=gi();
			double l1=b-a+1,l2=d-c+1;
			double s1=query(1,1,n,a,b),s2=query(1,1,n,c,d);
			modify_mul(1,1,n,a,b,(l1-1)/l1);
			modify_mul(1,1,n,c,d,(l2-1)/l2);
			modify_pls(1,1,n,a,b,1.0/l1*(s2/l2));
			modify_pls(1,1,n,c,d,1.0/l2*(s1/l1));
		}else{
			int a=gi(),b=gi();
			printf("%.5lf\n",query(1,1,n,a,b));
		}
	}
	return 0;
}
posted @ 2018-06-19 20:10  租酥雨  阅读(465)  评论(0编辑  收藏  举报