正题
很好的题。
设
我们把Snuke和Ringo的 路程-时间 折线投射在一个二维平面上,发现是要求一个最大的p,使得Ringo交x轴于(p,0),且与Snuke的折线有交点。
假设交x轴这条线段是k,那么对于它旁边的线段,需要满足
为什么是,考虑一条路径,从(p,0)开始,沿着Ringo的折线走,直到走到交点为止,然后走Snuke的折线,再走到(n,S)。
那么在k右边,我们肯定希望上升的越快越好,对于i,最多上升贡献为,我们需要构造一种方案来使得所有在k右边的线段既满足
,又满足每个对路径的上升贡献为
。
选出这些线段之后,只需要将的放在交点左边,
的放在交点右边就好了,放好了就知道交点一定是在一个整点上面。那么这就是一种方案。
我们按照排序,取出前q大,使得
答案至少是,为什么?首先当
时,显然;否则就肯定取到一个B_i,使得
,那么我们让那一条线段当作k就可以了。
接着我们枚举k是什么,进行更新就可以了。
发现出了k这条边,后面肯定是q-1条最大的边,否则答案只会更小。
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
struct node{
int a,b;
bool operator<(const node q)const{
return a>q.a;
}
}s[N];
int n;
long long sum=0;
long long gcd(long long x,long long y){
if(y==0) return x;
return gcd(y,x%y);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int x,y;
scanf("%d %d",&x,&y);
sum+=x;
s[i].a=max(x,y);s[i].b=y;
}
sort(s+1,s+1+n);
long long as=0;
int k=0;
while(1){
k++;
as+=s[k].a;
if(as>=sum) break;
}
long long ansx=1,ansy=1;
for(int i=1;i<=n;i++){
long long now=sum-(as-s[min(i,k)].a);
if(now<=s[i].b && now*ansy<1ll*s[i].b*ansx) ansx=now,ansy=s[i].b;
}
ansx=ansy-ansx+(n-k)*ansy;
ansy*=n;
printf("%lld %lld",ansx/gcd(ansx,ansy),ansy/gcd(ansx,ansy));
}
853

被折叠的 条评论
为什么被折叠?



