题目描述
Description
Input
Output
Sample Input
3
1 1
1 2
2 2
Sample Output
8.0000
Data Constraint
10%
暴力乱搞
60%
二分答案,求每个怪物对应的x(a和b的转换比率)范围,判断是否合法
100%
并不是网上的做法
貌似都不加O3时跑得最快+代码最短
后来发现是水法
首先设比率为x(a/b=x),则贡献为ai+bi+ai/x+bi*x
显然后面的是一个对勾函数,图像大致如下
首先对于两个怪物ij,如果ai>aj且bi>bj,则j不会影响到答案
所以排序后用栈维护一下,把没用的筛掉
最后剩下的都是ai<aj且bi>bj(i<j)
也就是说j的开始位置比i突出,且j的后面那一段比i要缓
这时可以发现,最终的答案一定是排序后第n个函数和1~i-1中某个的交点或n的最小值!
-2019年5月17日
既然是水法就随便讲讲。。
把a最大的和其它函数相交,把x最小的交点和a最大的函数的最小值位置取min,然后求值
其实可以被hack掉
正解网上搜,大概类似斜率优化
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define sqr(x) ((x)*(x))
#define Len 21000000
using namespace std;
struct type{
long long a,b;
} a[1000001],d[1000001];
char ch[Len];
int n,N,i,j,k;
char *Ch=ch;
long double ans,s;
int get()
{
int x=0;
while (*Ch<'0' || *Ch>'9') *++Ch;
while (*Ch>='0' && *Ch<='9') x=x*10+(*Ch-'0'),*++Ch;
return x;
}
bool cmp(type a,type b)
{
return a.a<b.a || a.a==b.a && a.b<b.b;
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("monster2.in","r",stdin);
fread(&ch,1,Len,stdin);
n=get();
fo(i,1,n)
{
a[i].a=get();
a[i].b=get();
}
sort(a+1,a+n+1,cmp);
fo(i,1,n)
{
while (N && d[N].b<=a[i].b) --N;
d[++N]=a[i];
}
ans=sqrt((long double)d[N].a/d[N].b);
fo(i,1,N-1)
{
s=(long double)(d[N].a-d[i].a)/(d[i].b-d[N].b);
ans=min(ans,s);
}
printf("%0.4Lf\n",d[N].a+d[N].b+d[N].a/ans+d[N].b*ans);
}