CF578C题解

看到题面的第一眼是这玩意儿关于 x 是单谷的,证明稍微想了一下:

f[k]g[k] 是原序列中长度为 k 的子区间的最大子区间和最小子区间,给定 x 时答案就相当于:

maxi=1nmax(|f[k]k×x|,|g[k]k×x|)

这相当于若干个一次函数取绝对值后的最值。我们知道两个单谷函数取 max 后仍然是单谷函数,斜率为负的一次函数取绝对值后也是单谷函数。

所以原问题的函数是若干个单谷函数取 max,也是单谷函数。

然后就可以愉快地三分了。自己使用的是微分,以及需要注意精度。

#include<cstdio>
typedef long double db;
const int M=2e5+5;
const db eps=1e-12;
int n,a[M];db b[M];
inline db fabs(const db&a){
	return a>0?a:-a;
}
inline db max(const db&a,const db&b){
	return a>b?a:b;
}
inline db min(const db&a,const db&b){
	return a>b?b:a;
}
inline db f(const db&x){
	db f(0),g(0),ans(0);
	for(int i=1;i<=n;++i)f=max(f,0)+a[i]-x,g=min(g,0)+a[i]-x,ans=max(ans,max(fabs(f),fabs(g)));
	return ans;
}
signed main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",a+i);
	db L(-10000),R(10000),mid;
	while(L+eps<R){
		mid=(L+R)/2;if(f(mid)<f(mid+eps))R=mid;else L=mid;
	}
	printf("%.10Lf",f(L));
}

本文作者:Prean

本文链接:https://www.cnblogs.com/lmpp/p/16596513.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Prean  阅读(34)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起