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; 
} 

猜你喜欢

转载自www.cnblogs.com/sssy/p/9574814.html