loj#2015. 「SCOI2016」妖怪 凸函数/三分

题目链接

loj#2015. 「SCOI2016」妖怪

题解

对于每一项展开
的到\(atk+\frac{dnf}{b}a + dnf + \frac{atk}{a} b\)
令$T = \frac{a}{b} $
原式$=atk+Tdnf + dnf + \frac{atk}{T} $
这就是那个单峰的对勾函数,
把单峰函数复合为求最值,发现也是个单峰函数(下凸壳)
三分就好了
或者维护一个最大值得下凸壳

代码

#include<cstdio> 
#include<algorithm> 

inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' || c > '9') c = getchar(); 
	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
	return x * f; 
} 
#define db double
const int maxn = 5000007; 

db atk[maxn],dnf[maxn]; 
int n; 
db calc(db T) { 
	double ret = 0.0; 
	for(int i = 1;i <= n;++ i) { 
		db tmp = dnf[i] + atk[i] + dnf[i] / T + atk[i] * T; 
		ret = std::max(tmp,ret); 
	} 
	return ret; 
} 
int main() { 
	n = read(); 
	for(int i = 1;i <= n;++ i) 
		scanf("%lf%lf",atk + i,dnf + i); 
	db l = 0,r = 10.0; 
	for(;r - l >= (1e-12);) { 
		db m1 = l + (r - l) / 3.0,m2 = r - (r - l) / 3.0; 
		db c1 = calc(m1),c2 = calc(m2);  
		if(c1 > c2) l = m1; 
		else r = m2; 
	} 
	printf("%.4lf\n",std::min(calc(r),calc(l))) ; 
	return 0; 
} 
posted @ 2018-09-02 19:08  zzzzx  阅读(301)  评论(2编辑  收藏  举报