【Loj #10013. 「一本通 1.2 例 3」曲线】题解

题目链接

题目

明明做作业的时候遇到了 nnn 个二次函数 Si(x)=ax2+bx+cS_i(x)= ax^2 + bx + cS​i​​(x)=ax​2​​+bx+c,他突发奇想设计了一个新的函数 F(x)=max{Si(x)},i=1…nF(x) = max{S_i(x)}, i = 1ldots nF(x)=max{S​i​​(x)},i=1…n。

明明现在想求这个函数在 [0,1000][0,1000][0,1000] 的最小值,要求精确到小数点后四位,四舍五入。

思路

三分模板。

在区间 \([0, 1000]\) 中进行三分,每次 \(O(n)\) 算出答案。

显然, 由于 \(s\) 函数满足单调性,\(f\) 函数是 \(s\) 函数中的最大值,必然也满足单调性。

Code

// Problem: #10013. 「一本通 1.2 例 3」曲线
// Contest: LibreOJ
// URL: https://loj.ac/p/10013
// Memory Limit: 512 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define N
//#define M
//#define mo
int n, m, i, j, k, t; 
double l, r, lmid, rmid, sum; 
double a[100010], b[100010], c[100010]; 

double check(double x)
{
	sum=-99999999999; 
	for(i=1; i<=n; ++i)
		sum=max(sum, a[i]*x*x+b[i]*x+c[i]); 
	return sum; 
}

signed main()
{
//	freopen("tiaoshi.in","r",stdin);
//	freopen("tiaoshi.out","w",stdout);
	t=read();
	while(t--)
	{
		n=read(); 
		for(i=1; i<=n; ++i)
			scanf("%lf%lf%lf", &a[i], &b[i], &c[i]); 
		l=0; r=1000; 
		while(r-l>0.00000000001)
		{
			lmid=l+(r-l)/3; 
			rmid=r-(r-l)/3; 
			if(check(lmid)>check(rmid)) l=lmid; 
			else r=rmid; 
		}
		printf("%.4lf\n", check(l)); 
	}
	return 0;
}

posted @ 2021-12-11 10:03  zhangtingxi  阅读(197)  评论(0编辑  收藏  举报