每个妖怪在指定环境下攻击和防御的变化量比值是一个定值,所以我们可以把妖怪看成平面上的点,横纵坐标为攻击和防御,对于每个妖怪环境看成一条k=-b/a的过该妖怪直线,每个妖怪的战斗力就是x=0时y的值加上y=0时x的值
所以我们要维护一个右上凸壳,用一条直线卡这个凸壳,假设卡到的妖怪是(x,y),我们可以用x+y-kx-y/k更新答案
对于每个单独妖怪,战斗力=x+y-kx-y/k,对勾函数,当k=-sqrt(y/x)时取得最小值
维护一个右上凸壳,对于每个凸壳上的妖怪,用他和他上一个妖怪连成的直线更新答案,然后算出这个妖怪的最优斜率,如果这个斜率的直线卡在凸包上的妖怪是这个妖怪则更新答案
复杂度O(n logn)
如果二分写的很优的话也可以过
设t=b/a
二分答案c,如果存在一个t使得对于所有妖怪x+y+tx+y/t<=c有解则c可行
等式两边同时乘以x,变为二次函数,相当于数轴上线段判有没有交,每次可以O(n)判断
复杂度O(n logINF/eps)反正我是特勒了
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 1000010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
char xB[1<<15],*xS=xB,*xT=xB;
#define getc() (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
inline int read(){
char ch=getc();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getc();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getc();}
return x*f;
}
struct pt{
int x;
int y;
pt(){
}
pt(int _x,int _y){
x=_x;
y=_y;
}
friend pt operator -(pt x,pt y){
return pt(x.x-y.x,x.y-y.y);
}
friend double operator *(pt x,pt y){
return 1.0*x.x*y.y-1.0*x.y*y.x;
}
friend bool operator <(pt x,pt y){
return x.x!=y.x?x.x<y.x:x.y>y.y;
}
};
int n;
pt a[MAXN];
pt s[MAXN];
int tp;
double ans=1e10;
double k(pt &x){
return -sqrt(1.0*x.y/x.x);
}
double xl(pt &x,pt &y){
return x.x==y.x?-1e60:1.0*(x.y-y.y)/(x.x-y.x);
}
double cal(pt x,double k){
if(fabs(k)<eps){
return 1e20;
}
return 1.0*x.x+x.y-1.0*x.x*k-1.0*x.y/k;
}
int main(){
int i;
n=read();
for(i=1;i<=n;i++){
a[i].x=read();
a[i].y=read();
}
sort(a+1,a+n+1);
for(i=1;i<=n;i++){
while(tp>=2&&(s[tp]-s[tp-1])*(a[i]-s[tp])>0){
tp--;
}
s[++tp]=a[i];
}
double K;
if(tp!=1){
K=k(s[1]);
if(K>=xl(s[1],s[2])){
ans=min(ans,cal(s[1],K));
}
K=k(s[tp]);
if(K<=xl(s[tp-1],s[tp])){
ans=min(ans,cal(s[tp],K));
}
ans=min(ans,cal(s[tp],xl(s[tp-1],s[tp])));
}else{
ans=cal(s[1],k(s[1]));
}
for(i=2;i<tp;i++){
K=k(s[i]);
if(K<=xl(s[i-1],s[i])&&K>=xl(s[i],s[i+1])){
ans=min(ans,cal(s[i],K));
}
ans=min(ans,cal(s[i],xl(s[i-1],s[i])));
}
printf("%.4lf\n",ans);
return 0;
}
/*
*/