• 三分 + 最大区间和


    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.

    Example
    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.

    题意 : 寻找一个X ,让数组中的全部元素都减去 x ,找区间和最大的情况,所求答案是所有可能情况下最小的答案。

    思路分析 : 当 X 很大时,答案也会是一个很大的值,当 X 很小时,答案也会是一个很大的值,所以,只有当 X 适当时才会有最小的答案,那么这里显然就是三分,图像是一个凹函数,三分判断的条件就是一个求一个最大区间和就可以,因为区间绝对值和最大,它产生的情况有两种,一种区间的和是正值最大,一种区间的和是负值,让它最小,则绝对值会大。

    代码示例 :

    #define ll long long
    const int maxn = 2e5+5;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    
    double arr[maxn];
    double pp[maxn];
    int n;
    double dp[maxn], dp2[maxn];
    double ans = 1.0*inf;
    
    double abc(double x){
        return x < 0?-x:x;
    }
    
    double fun(double x){
        for(int i = 1; i <= n; i++){
            pp[i] = arr[i] - x;
        }   
        memset(dp, 0, sizeof(dp));
        memset(dp2, 0, sizeof(dp2));
        double num = -1.0*inf;
        for(int i = 1; i <= n; i++){
            dp[i] = max(dp[i], dp[i-1]+pp[i]);
            dp2[i] = min(dp2[i], dp2[i-1]+pp[i]);
            double f = abc(dp[i]), f2 = abc(dp2[i]);
            num = max(f, num);
            num = max(f2, num); 
        }   
        return num;
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        
        cin >> n;
        for(int i = 1; i <= n; i++){
            scanf("%lf", &arr[i]);
        }
        double l = -20000, r = 20000;
            
        for(int i = 1; i <= 100; i++){
            double lm = l + (r-l)/3;
            double rm = r - (r-l)/3;
            double lf = fun(lm);
            double rf = fun(rm);
            if (lf > rf) {
                l = lm;
                ans = min(ans, rf);
            } 
            else {
                r = rm;
                ans = min(ans, lf);
            }  
        }
        printf("%.15lf
    ", ans);    
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    汇编 Hello Window [菜鸟]疑问
    得到指定进程所有窗口。显示 影藏 置顶。
    汇编,SendMessage和WM_SETTEXT
    C#: 字段和局部变量的作用域冲突
    C#: 给方法传递参数
    C#:类和结构
    C#: string 类型
    Copy files to a folder which need have Administrator approve and overwrite the existing same readonly files
    C#:构造函数
    C#:数组, 命名空间, Main()方法
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8457021.html
Copyright © 2020-2023  润新知