弱さと悪さCodeForces - 578C(三分)

あなたは、...、のシーケンスを与えられたn個の整数は、A1、A2います。

X、A2 - - X、...、 - xは可能な限り小さくある。シーケンスa1の弱さがあるよう実数Xを決定します

配列の弱さは、配列のすべてのセグメント(隣接配列)上悪さの最大値として定義されます。

セグメントの悪さは、セグメントの要素の総和の絶対値として定義されます。

入力
最初の行は、一つの整数N(1≤N≤200 000)、配列の長さを含みます。

2行目は含まれていnは整数A1、A2、...、(|愛|≤10 000)。

出力
A1の最小の可能な弱さを示す出力実数- X、A2 - X、...、X - 。6 -その相対的または絶対誤差が10を超えていない場合はあなたの答えが正しいとみなされます。


入力
3
1 2 3
出力
1.000000000000000
入力
4
1つの2 3 4
出力
2.000000000000000
入力
10
1 10 2 9 3 8 4 7 5 6
出力
4.500000000000000

、1 -最初のケースでは、xの最適値は、2配列になるようです0、1とmax悪さは、セグメント「-1」又はセグメント「1」で起こります。悪値(答えは)このような場合には1に等しいです。

1.5 - - 0.5、0.5、1.5および最大悪さは、セグメント上で発生する「-1.5 -0.5」又は「0.5~1.5」配列となるように、第2のサンプルについてのXの最適値は2.5です。悪値(答えは)この場合は2に等しいです。

タイトルの意味:
列数A1、A2、A3 ...。あなたは、列の数がA1-X、A2-X、なるように、xの数から選択することができる A3-X···-X。
サブセグメントの列数の絶対最大値。使用可能な列の最小数を探しています。
思考:
と仮定すると、SKの値{maxの- X K}。長さkのサブセグメントのSKを表します。
xの各要素値の列の数の増加に伴って明らかにXで単調に減少する、ますます小さくなります。
次に{マックス|、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 ビュー30000 +

おすすめ

転載: blog.csdn.net/tomjobs/article/details/104252494