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

来源:互联网 发布:阿里云 apk 编辑:程序博客网 时间:2024/05/17 18:11

网上很多人写这道题目是三分+最大(小)子段和,但是这道题目是可以二分的,看我的二分内容

//我们的目的是让最小字段和和最大字段和相等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-12int 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;}
0 0