AGC040D - Balance Beam

\(n\)个边,长度相同,对于A来说经过某条边需要花\(a_i\)时间,对于B来说需要花\(b_i\)时间。

把边排列之后连成一条链,A从左端点开始向右走,B随机在链上某一点(实数域内)出发向右走。

现在要决定这个排列,使得A和B相遇的概率尽量大。

\(n\le 10^5\)


假设排列固定。以位置-时间建系,从原点开始分别画出A和B的图象。然后将B的图象纵向平移,直到再向下平移不可能和A的图象相交为止(刚好相交)。设此时B的图象和x轴的交点为\((p,0)\)。我们希望最大化\(p\)

有点性质:此时A和B的图象只会在整点相交。因为刚好相交,所以B的图象在所有的位置小于等于A的图象;如果不在整点相交,因为斜率没有发生改变,一定会出现“穿过”的情况。

考虑从\((p,0)\)开始,先走B的图象,在第一次相交处走A的图象。由于终点是\((n,S)\)(设\(S=\sum a_i\)),固定的,于是最大化\(p\)相当于最大化\((p,0)\)\((n,S)\)的斜率。路径每段的增量至多是\(\max(a_i,b_i)\)

枚举\((p,0)\)所对应的边为\(k\),假设已经决定了排在\(k\)后面的边的边集。首先要有\(b_k+\sum_{后面的i} \max(a_i,b_i)\ge S\)。将\(b_i>a_i\)的放前面,其它的放后面,以下说明这样就达到了上限。

这样排列之后,在\(b_i>a_i\)的段中,A和B的相对位移不断减少。所以在\(b_i\)\(a_i\)大小关系转变的那一刻,A和B的相对位移达到极值。因为A和B图象恰好相交(于是相对位移大于等于\(0\)),所以达到极值的那一刻,两者相交。此时就会从走B的图象走到A的图象。

又因为前面\(b_i>a_i\),贡献\(b_i=\max(a_i,b_i)\),后面类似,所以达到上限。

既然我们希望最大化\((p,0)\)\((n,S)\)的斜率,那么这个边集就可以贪心取,按照\(\max(a_i,b_i)\)从大到小排序,找到最小前缀满足\(b_k+\sum_{i} \max(a_i,b_i)\ge S\)。于是\(\lceil p\rceil\)就已经确定了,小数部分进一步算一下即可。

注意:如果二分出来得到\(\sum_i \max(a_i,b_i)> S\),则不能算入答案。因为此时不管怎样从\((p,0)\)出发都能到达大于\((n,S)\)的地方。


using namespace std;
#include <bits/stdc++.h>
#define N 100005
#define ll long long
#define db long double
ll gcd(ll a,ll b){
	ll k;
	while (b)
		k=a%b,a=b,b=k;
	return a;
}
int n;
struct info{int a,b;} d[N];
bool cmpd(info x,info y){return max(x.a,x.b)>max(y.a,y.b);}
ll ps[N],sa;
struct frac{
	ll u,v;
	frac(ll _u=0,ll _v=0){u=_u,v=_v;}
	void adj(){
		ll g=gcd(u,v);
		u/=g,v/=g;
	}
};
bool operator<(frac x,frac y){
	return (db)x.u*y.v<(db)y.u*x.v;
}
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%d",&n);
	for (int i=1;i<=n;++i){
		scanf("%d%d",&d[i].a,&d[i].b);
		sa+=d[i].a;	
	}
	sort(d+1,d+n+1,cmpd);
	for (int i=1;i<=n;++i)
		ps[i]=ps[i-1]+max(d[i].a,d[i].b);
	frac ans(0,1);
	for (int k=1;k<=n;++k){
		//printf("k=%d\n",k);
		if (d[k].b+ps[k-1]>=sa){
			int pos=lower_bound(ps,ps+k,sa-d[k].b)-ps;
			if (pos<k){
				ll s=ps[pos];
				if (sa-s>=0)
				//printf("%d %lld (%lld,%lld)\n",n-pos,s,(ll)(n-pos)*d[k].b-(sa-s),(ll)d[k].b);
				ans=max(ans,frac((ll)(n-pos)*d[k].b-(sa-s),d[k].b));
				//printf("(%lld,%lld)\n",ans.u,ans.v);
			}
		}
		else{
			int pos=lower_bound(ps+k,ps+n+1,sa-d[k].b+max(d[k].a,d[k].b))-ps;
			if (pos<=n){
				ll s=ps[pos]-max(d[k].a,d[k].b);
				if (sa-s>=0)
				//printf("%d (%lld,%lld)\n",n-(pos-1),sa-s,(ll)d[k].b);
				ans=max(ans,frac((ll)(n-(pos-1))*d[k].b-(sa-s),d[k].b));
				//printf("(%lld,%lld)\n",ans.u,ans.v);
			}
		}
	}
	ans.v*=n;
	ans.adj();
	printf("%lld %lld\n",ans.u,ans.v);
	return 0;
}
posted @ 2021-05-05 17:24  jz_597  阅读(66)  评论(0编辑  收藏  举报