当前位置: 首页 > 工具软件 > gym-fx > 使用案例 >

Gym - 100520B - 数学

施凡
2023-12-01

题目链接:https://vjudge.net/problem/Gym-100520B

 

解题思路:

算出每个线段的x区间,那么选择一个区间使得选到这里面达到条件的概率是A,也就是选择区间里的满足条件的长度刚好是总长度*A。因为超过是没意义的。那么也就是枚举l左端点,或者r右端点就行了。枚举l的左端点就是在每段线段的可行区间的左端点,枚举r右端点也就是每段可行的右端点。最后注意线段与x轴平行的情况就行了。

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
int n;
double l,r,A;
struct point
{
	double x,y;
}s[mx],p[mx];
typedef point vec; 
double sum[mx];
double GetP(point a,point b,double y)
{
	if(y<=min(a.y,b.y))
	{
		if(a.y<b.y) return a.x;
		return b.x;
	}
	if(y>=max(a.y,b.y)){
		if(a.y<b.y) return b.x;
		return a.x;
	}
	double y0 = a.y - y;
	double y1 = b.y - y;
	return (y1*a.x-y0*b.x)/(y1-y0);
}
double ans,L,R;
void solve1(double m)
{
	double ret = 0;
	int now = 1;
	for(int i=1;i<=n;i++){
		while(now<=n&&ret+p[now].y-p[now].x<m)
		{
			ret += p[now].y-p[now].x;
			now++;
		}
		if(now>n) break;
		double kep = m - ret;
		double fx = p[now].x + kep;
		if(fx-p[i].x<ans){
			ans = fx - p[i].x;
			L = p[i].x,R = fx;
		}
		ret = sum[now-1] - sum[i-1];
		if(now>i) ret -= p[i].y - p[i].x;
		if(now==i) now++;
	}
}
void solve2(double m)
{
	double ret = 0;
	int now = n;
	for(int i=n;i>0;i--){
		while(now&&ret+p[now].y-p[now].x<m)
		{
			ret += p[now].y-p[now].x;
			now--;
		}
		if(now==0) break;
		double kep = m - ret;
		double fx = p[now].y - kep;
		if(p[i].y-fx<ans){
			ans = p[i].y - fx;
			L = fx,R = p[i].y;
		}
		ret = sum[i] - sum[now];
		if(now<i) ret -= p[i].y - p[i].x;
		if(now==i) now--;
	}
}
int main()
{
	freopen("bayes.in ","r",stdin);
	freopen("bayes.out","w",stdout);
	while(scanf("%d",&n)&&n)
	{
		scanf("%lf%lf",&l,&r);
		scanf("%lf",&A);
		for(int i=0;i<=n;i++){
			scanf("%lf%lf",&s[i].x,&s[i].y);
		}
		ans = 1e40;
		double len = 0;
		for(int i=1;i<=n;i++){
			sum[i] = sum[i-1];
			if(s[i].y==s[i-1].y)
			{
				if(l<=s[i].y&&r>=s[i].y){
					p[i].x = s[i-1].x,p[i].y = s[i].x;
					len += s[i].x - s[i-1].x;
					sum[i] += s[i].x - s[i-1].x;
				}
				else p[i].x = p[i].y = s[i].x;
				continue;
			}
			if(r<=min(s[i].y,s[i-1].y)||l>=max(s[i].y,s[i-1].y))
			{
				p[i].x = p[i].y = s[i].x;
				sum[i] = sum[i-1];
				continue;
			}
			p[i].x = GetP(s[i-1],s[i],l);
			p[i].y = GetP(s[i-1],s[i],r);
			if(p[i].x>p[i].y) swap(p[i].x,p[i].y);
			len += p[i].y - p[i].x;
			sum[i] += p[i].y - p[i].x; 
		}
		A *= len;
		solve1(A);
		solve2(A);
		printf("%.8lf %.8lf\n",L,R);
	}
    return 0;
}

 

 类似资料: