strength=atk*(1+b/a)+dnf*(1+a/b)。设a/b=x,可以发现这是一个关于x的对勾函数。开口向上的一堆凸函数取max还是凸函数,三分即可。

  然而无良出题人既卡精度又卡时间。众所周知三分的本质是二分(雾),所以开始三分时令每次取的两个点为中点±eps,最后再用真的三分微调即可。具体边界多试几次就行了。跑的挺快还能剩下1s(大雾)。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000010
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int n;
struct data{int x,y;
}a[N];
double calc(double x)
{
double s=;
for (int i=;i<=n;i++) s=max(s,a[i].x*(+x)+a[i].y*(+/x));
return s;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4570.in","r",stdin);
freopen("bzoj4570.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) a[i].x=read(),a[i].y=read();
double eps=1E-;
double l=eps,r=/eps;
while (l+1E-<=r)
{
double mid1=(l+r)/-eps,mid2=(l+r)/+eps;
if (calc(mid1)<calc(mid2)) r=mid2;
else l=mid1;
}
for (int i=;i<=;i++)
{
double mid1=l+(r-l)/,mid2=r-(r-l)/;
if (calc(mid1)<calc(mid2)) r=mid2;
else l=mid1;
}
printf("%.4f",calc(l));
return ;
}
05-13 15:59