Weakness and Poorness CodeForces - 578C(三分)

You are given a sequence of n integers a1, a2, …, an.

Determine a real number x such that the weakness of the sequence a1 - x, a2 - x, …, an - x is as small as possible.

The weakness of a sequence is defined as the maximum value of the poorness over all segments (contiguous subsequences) of a sequence.

The poorness of a segment is defined as the absolute value of sum of the elements of segment.

Input
The first line contains one integer n (1 ≤ n ≤ 200 000), the length of a sequence.

The second line contains n integers a1, a2, …, an (|ai| ≤ 10 000).

Output
Output a real number denoting the minimum possible weakness of a1 - x, a2 - x, …, an - x. Your answer will be considered correct if its relative or absolute error doesn’t exceed 10 - 6.

Examples
Input
3
1 2 3
Output
1.000000000000000
Input
4
1 2 3 4
Output
2.000000000000000
Input
10
1 10 2 9 3 8 4 7 5 6
Output
4.500000000000000
Note
For the first case, the optimal value of x is 2 so the sequence becomes  - 1, 0, 1 and the max poorness occurs at the segment “-1” or segment “1”. The poorness value (answer) equals to 1 in this case.

For the second sample the optimal value of x is 2.5 so the sequence becomes  - 1.5,  - 0.5, 0.5, 1.5 and the max poorness occurs on segment “-1.5 -0.5” or “0.5 1.5”. The poorness value (answer) equals to 2 in this case.

题意:
数列a1,a2,a3…an。可以选一个数x使得数列变成a1-x,a2-x,a3-x…an-x。
数列的值为子段绝对值的最大值。求一个数列可得的最小值。
思路:
假设这个值为max{Sk - xk}。Sk代表某长度为k的子段。
随着x的增大数列各元素的值会越来越小,很明显是随x单调递减的。
那么max{|Sk - x
k|}的图像为单调函数按照某个点对称翻折后的图像,明显是单峰的。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const double eps = 4e-12;
const double INF = 0x3f3f3f3f;
const int maxn = 2e5 + 7;
int n;
double a[maxn],b[maxn],c[maxn];
double sum1[maxn],sum2[maxn];
double f(double x)
{
    double mx1 = -100000.0,mx2 = -100000.0;
    double now1 = 0.0,now2 = 0.0;
    for(int i = 1;i <= n;i++)
    {
        b[i] = a[i] - x;
        c[i] = -b[i];
        if(now1 < 0.0)now1 = 0.0;
        if(now2 < 0.0)now2 = 0.0;
        now1 += b[i];now2 += c[i];
        mx1 = max(now1,mx1);mx2 = max(mx2,now2);
    }
    return max(mx1,mx2);
}

double f2(double x)
{
    double mx1 = -100000.0,mx2 = -100000.0;
    sum1[0] = 0.0;sum2[0] = 0.0;
    for(int i = 1;i <= n;i++)
    {
        b[i] = a[i] - x;
        c[i] = -b[i];
        sum1[i] = max(sum1[i - 1] + b[i],b[i]);
        sum2[i] = max(sum2[i - 1] + c[i],c[i]);
        mx1 = max(sum1[i],mx1);mx2 = max(sum2[i],mx2);
    }
    return max(mx1,mx2);
}

int main()
{
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)
    {
        scanf("%lf",&a[i]);
    }
    
    double l = -20000.0,r = 20000.0;
    double ans = 0.0;
    int cnt = 0;
    while(r - l > eps)
    {
        double m1 = l + (r - l) / 3.0,m2 = l + 2.0 * (r - l) / 3.0;
//        printf("%.20f %.20f\n",l,r);
        if(f(m1) < f(m2))
        {
            ans = m1;
            r = m2;
        }
        else
        {
            ans = m2;
            l = m1;
        }
    }
    
    printf("%.6f\n",f(ans));
    return 0;
}

发布了676 篇原创文章 · 获赞 18 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104252494