2018-3-21模拟考试 期望

Posted on 2018-03-28 22:15  SirKnight  阅读(94)  评论(0)    收藏  举报

发现一次交换后,对于一个区间,单点有len(区间长度)-1/len的概率还是它自己,有1/len乘1/len1的概率变成另一个区间的任何一个数,线段树维护加法和乘法即可。

#include <stdio.h>
using namespace std;

const int maxn=400001;

struct node
{
	int l,r;
	double sum;
	double f1,f2;
}tree[maxn*8]; 

double a[maxn];
double ans;
int n,q;

int read()
{
	char ch=getchar();
	int flag=1,x=0;
	while((ch<'0'||ch>'9')&&ch!='-')
		ch=getchar();
	if(ch=='-')
	{
		flag=-1;
		ch=getchar(); 
	}
	while(ch>='0'&&ch<='9')
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*flag;
}

void pushup(int x)
{
	tree[x].sum=tree[x*2].sum+tree[x*2+1].sum;
}

void pushdown(int x)
{
	tree[x*2].sum=tree[x*2].sum*tree[x].f2+tree[x].f1*(tree[x*2].r-tree[x*2].l+1);
	tree[x*2+1].sum=tree[x*2+1].sum*tree[x].f2+tree[x].f1*(tree[x*2+1].r-tree[x*2+1].l+1);
	tree[x*2].f1=tree[x*2].f1*tree[x].f2+tree[x].f1,tree[x*2].f2*=tree[x].f2;
	tree[x*2+1].f1=tree[x*2+1].f1*tree[x].f2+tree[x].f1,tree[x*2+1].f2*=tree[x].f2;
	tree[x].f1=0,tree[x].f2=1;
}

void build(int x,int lt,int rt)
{
	tree[x].l=lt,tree[x].r=rt,tree[x].f2=1;
	if(lt==rt)
	{
		tree[x].sum=a[lt];
		return;
	}
	int mid=(lt+rt)/2;
	build(x*2,lt,mid);
	build(x*2+1,mid+1,rt);
	pushup(x);
}

void add(int x,double l1,double r1,int l2,int r2,double temp)//一定要开double(除法) 
{
	if(tree[x].l>r1||tree[x].r<l1)
		return;
	if(tree[x].l>=l1&&tree[x].r<=r1)
	{
		tree[x].sum=temp*(tree[x].r-tree[x].l+1)/((r1-l1+1)*(r2-l2+1))+tree[x].sum*(r1-l1)/(r1-l1+1);
		tree[x].f1=tree[x].f1*(r1-l1)/(r1-l1+1)+temp/((r1-l1+1)*(r2-l2+1));//lazy是单点的 
		tree[x].f2*=(r1-l1)/(r1-l1+1);
		return;
	}
	pushdown(x);
	int mid=(tree[x].l+tree[x].r)/2;
	if(mid>=l1)
		add(x*2,l1,r1,l2,r2,temp);		
	if(mid<r1)
		add(x*2+1,l1,r1,l2,r2,temp);
	pushup(x);
}

void query(int x,int lt,int rt)
{
	if(tree[x].l>rt||tree[x].r<lt)
		return;
	if(tree[x].l>=lt&&tree[x].r<=rt)
	{
		ans+=tree[x].sum;
		return;
	}
	pushdown(x);
	int mid=(tree[x].l+tree[x].r)/2;
	if(mid>=lt)
		query(x*2,lt,rt);		
	if(mid<rt)
		query(x*2+1,lt,rt);
	pushup(x);
}

int main()
{
	n=read(),q=read();
	int i;
	for(i=1;i<=n;i++)
		a[i]=read();
	build(1,1,n);
	for(i=1;i<=q;i++)
	{
		int opr;
		opr=read();
		if(opr==1)
		{
			int l1,r1,l2,r2;
			l1=read(),r1=read(),l2=read(),r2=read();
			ans=0;
			query(1,l1,r1);
			double temp1=ans;
			ans=0;
			query(1,l2,r2);
			double temp2=ans;
			add(1,l1,r1,l2,r2,temp2),add(1,l2,r2,l1,r1,temp1);
		}
		if(opr==2)
		{
			int lt,rt;
			lt=read(),rt=read();
			ans=0;
			query(1,lt,rt);
			printf("%.7lf\n",ans);
		}
	}	
	return 0;
}