ICPC North Central NA Contest 2018 H. New Salaries 数学分析+前缀和维护

两个线段一左一右,题目保证了l[i-1]<=l[i]  r[i-1]<=r[i]

则只会出现相交一段,或相离2种情况。

分情况讨论把分别的期望算出来。对于两段:

[l_j,r_j],[l_i,r_i](j<i)

第一种:相离:为了方便书写我们用[a,b][c,d]表示:

显然E(|X-Y|)=\frac{c+d}{2}-\frac{a+b}{2}

第二种 相交:如下所示

此时:对于ab这条线段

当a<=y<=c时,E(|X-Y|\& \&a<=Y<=c) \frac {c-a} {b-a} *(\frac{d+c}{2}-\frac{a+c}{2})

 

当c<=y<=b时,

对于x,b<=x<=d时

E(|X-Y|\& \&c<=Y<=b\& \&\ b<=X<=d)= \frac {b-c} {b-a} *(\frac{d+b}{2}-\frac{b+c}{2})

对于x,c<=x<=b时

\int _c^b\int _c^b(f(x)*f(y)*|x-y|)dxdy  

f(x),f(y)时概率密度函数,由于x,y服从均匀分布所以f(x)=f(y)=\frac{1}{b-c}

去掉绝对值后,解这个二重积分可得:

2*\int _x^b\int _c^b(f(x)*f(y)*|x-y|)dxdy=\frac{b-c}{3}

E(|X-Y|\& \&c<=Y<=b\& \&\ c<=X<=b) =\frac{b-c}{3}*\frac{b-c}{b-a}*\frac{b-c}{d-c}

把上面三个期望求和即相交的总期望。

E{|X-Y|}=\frac{c+d}{2}-\frac{a+b}{2}+\frac{(b-a)^3}{3*(d-c)(b-a)}

相离时的期望:E{|X-Y|}=\frac{c+d}{2}-\frac{a+b}{2}

发现只有后面不同,把后面那个式子分子分解,枚举i,找到所有j使得j<i,且i与j的线段相交。

利用前缀和即可快速算出。

这里直接贴下别人的题解里的图片。markdown打的太慢了。。

这题精度要求比较高 用long double 保险。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double db;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double eps=1e-6;
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){ee[++cnt].nxt=head[x],ee[cnt].to=y,head[x]=cnt;}
*/

db l[M],r[M];
db len[M];
db s1[M];//(lj+rj)/2  前缀和 
db s2[M];//1/(rj-lj) 前缀和 
db s3[M];//rj^3/(rj-lj)前缀和 
db s4[M];//rj^2/(rj-lj) 前缀和
db s5[M];//rj/(rj-lj)  前缀和 
int main()
{
	freopen("30.in","r",stdin);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		scanf("%Lf%Lf",&l[i],&r[i]);
		len[i]=r[i]-l[i];
		s1[i]=s1[i-1]+(l[i]+r[i])/2;
		if(fabs(len[i])<=eps)
		{
			s2[i]=s2[i-1];s3[i]=s3[i-1];s4[i]=s4[i-1];s5[i]=s5[i-1];
			continue;
		}
	//	cout<<len[i]<<endl;
		db t=1.0;
		s2[i]=s2[i-1]+t/len[i];
		t*=r[i];s3[i]=s3[i-1]+t/len[i];
		t*=r[i];s4[i]=s4[i-1]+t/len[i];
		t*=r[i];s5[i]=s5[i-1]+t/len[i];
	}
	db ans=0;
	for(int i=1;i<=n;i++)
	{
		ans+=1.0*(i-1)*(l[i]+r[i])/2-s1[i-1];
		if(fabs(len[i])<eps)continue;
		int p=upper_bound(r+1,r+n+1,l[i])-r;
		db m2=(s2[i-1]-s2[p-1]),m3=(s3[i-1]-s3[p-1]),m4=(s4[i-1]-s4[p-1]),m5=(s5[i-1]-s5[p-1]);
		db tp=1.0;
	//	cout<<ans<<"- "<<endl;
		ans+=tp/len[i]*m5/3;tp*=l[i];
		ans-=tp/len[i]*m4;tp*=l[i];
		ans+=tp/len[i]*m3;tp*=l[i];
		ans-=tp/len[i]*m2/3;
	//	cout<<i<<" "<<p<<"  "<<ans<<" "<<(l[i]+r[i])/2<<" "<<s1[i-1]<<endl;
	}
	ans=ans/n/n;
	printf("%.10Lf\n",ans);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值