其他分享
首页 > 其他分享> > 6. Lots of Parabolas

6. Lots of Parabolas

作者:互联网

题目链接:Lots of Parabolas

学长分享的一道有趣的题。抛物线开口指向的区域称为抛物线的内部,给出很多抛物线方程,请你输出一个位于所有抛物线内部的点。

可以根据二次项系数的正负将所有抛物线分为向上和向下的两类。对于向上的抛物线,取最大值后可以形成一个先减后增的单峰函数 \(f\),对于向下的抛物线,取最小值后会形成一个先增后减的单峰函数 \(g\)。显然,这个点会存在于这两个单峰函数的图像之间。将这两个单峰函数相减,形成的函数依然是单峰函数。三分这个单峰函数,其极值点处应该是最有可能成为答案的地方,在这里取 \(f\) 和 \(g\) 的平均值作为答案的纵坐标。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const double eps = 1e-8;
struct node {
    double a, b, c;
};
vector<node> up, down;
double f(double x) {
    double ret = -1e30;
    for (auto &i : up) {
        ret = max(ret, i.a * x * x + i.b * x + i.c);
    }
    return ret;
}
double g(double x) {
    double ret = 1e30;
    for (auto &i : down) {
        ret = min(ret, i.a * x * x + i.b * x + i.c);
    }
    return ret;
}
double calc(double x) { return f(x) - g(x); }
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 1, a, b, c; i <= n; ++i) {
        cin >> a >> b >> c;
        if (a > 0)
            up.push_back({a, b, c});
        else
            down.push_back({a, b, c});
    }
    double l = -1e9, r = 1e9;
    while (fabs(l - r) > eps) {
        double midl = (2 * l + r) / 3, midr = (l + 2 * r) / 3;
        if (calc(midl) < calc(midr))
            r = midr;
        else
            l = midl;
    }
    cout << fixed << setprecision(6) << l << ' ' << (f(l) + g(l)) / 2.0 << endl;
    return 0;
}

标签:单峰函数,Lots,double,ret,Parabolas,int,抛物线,return
来源: https://www.cnblogs.com/theophania/p/p6.html