您的位置:首页 > 其它

Codeforces 578C Weakness and Poorness(二分 + 最大(小)子段和)

2015-09-28 22:47 260 查看
网上很多人写这道题目是三分+最大(小)子段和,但是这道题目是可以二分的,看我的二分内容

//我们的目的是让最小字段和和最大字段和相等
bool Calc(double x)
{
//MN、MX分别是最小最大子段和
if(MN > eps) return 1;     //当最小子段和比0大时减小(-x)(ps:我是写的a[i] = a[i]+x)
if(MX < eps) return 0;     //当最大子段和比0小时增大(-x)
return fabs(MN) - MX < eps;//当最小子段和比最大子段和小的时候让(-x)减小,反之增大。
}
//以下是二分部分
mid = (l + r) / 2.0;
if(Calc(mid)) r = mid;
else l = mid;


给出完整代码:

#include<cstdio>
#include<cmath>
#define max(a, b) (a) > (b) ? (a) : (b)
#define min(a, b) (a) < (b) ? (a) : (b)
#define MAXN 200005
#define eps 1e-12
int n;
double a[MAXN], MX, tmpx, MN, tmpn;
bool Calc(double x)
{
MX = MN = tmpn = tmpx = a[1] + x;
for(int i = 2; i <= n; i ++) {
tmpx = max(tmpx + a[i] + x, a[i] + x);
MX = max(tmpx, MX);
tmpn = min(tmpn + a[i] + x, a[i] + x);
MN = min(tmpn, MN);
}
if(MN > eps) return 1;
if(MX < eps) return 0;
return fabs(MN) - MX < eps;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%lf", a + i);
double l = -10000.0000001, r = 10000.0000001, mid;
for(int i = 1; i <= 60; i ++) {
mid = (l + r) / 2.0;
if(Calc(mid)) r = mid;
else l = mid;
}
printf("%.9lf", MX);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: