Error Curves (三分) (2023-02-18)

题目链接: https://vjudge.net/contest/537370#problem/H

题意

给出 t 组数据,对于每一组数据,给出 n 个一元二次方程 fi(x)=ax+bx+c 的系数 a, b, c,得到一个新的曲线 g(x) = max{sigma(fi(x))},求 g(x) 的最小值。

(T < 100) (n ≤ 10000) (0 ≤ a ≤ 100), (|b| ≤ 5000), (|c| ≤ 5000), 0 ≤ x ≤ 1000

思路

简单画个图分析一下可以得到新曲线 g(x) 也是一条与一元二次方程类似的先单调下降后单调上升的曲线。

然后就可以三分这个最低点。

复杂度 O(log(1000/eps))。

代码

#include <cstdio>
#include <vector>

#define NL putchar(10);

const int maxN = 2e5;
const double eps = 1e-15;

int n; double a[maxN], b[maxN], c[maxN];

double check(double x) {
  double max; bool fst = 1;
  for(int i = 0; i < n; ++i) {
    const double cur = (a[i]*x*x+b[i]*x+c[i]);
    max = fst ? (fst=0,cur) : max > cur ? max : cur;
  }
  return max;
}

int main() {
  int t; scanf("%d", &t);
  while(t--) {
    scanf("%d", &n);
    for(int i = 0; i < n; ++i) { scanf("%lf%lf%lf", a+i, b+i, c+i); }
    double l = 0.0, r = 1000.0;
    while(l < r-eps) {
      const double m1 = l+(r-l)/3.0, m2 = l+2*(r-l)/3.0;
      const double y1 = check(m1), y2 = check(m2);
      if (y1 > y2) { l = m1; }
      else { r = m2; }
    }
    printf("%.4f", check(r)); NL;
  }
  return 0;
}