[Codeforces Round #320 (Div. 2) -E. Weakness and Poorness (三分/二分)

E. Weakness and Poorness

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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

Determine a real number x such that the weakness of the sequence a1 - x, a2 - x, ..., a**n - 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, ..., a**n (|a**i| ≤ 10 000).

Output

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

Examples

input

Copy

3
1 2 3

output

Copy

1.000000000000000

input

Copy

4
1 2 3 4

output

Copy

2.000000000000000

input

Copy

10
1 10 2 9 3 8 4 7 5 6

output

Copy

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.

题意:

给你一个长度为\(\mathit n\)的数组\(\mathit a\)

让你寻找一个实数\(\mathit x\),使\(a_1-x,a_2-x,a_3-x,\dots,a_n-x\)的weakness最小。

一个数组的的weakness值是数组所有连续子段的poorness值的最大值。

一个子段的poorness的值是这段子段的数值sum和的绝对值。

思路:

我们定义\(S(i,j)=\sum_{k=i}^j (a_k-x)\)

那么数值\(\mathit a\)的weakness值为:\(max(|S(i,j)|,1\leq i\leq j\leq n\)

\(|S(i,j)|=max(S(i,j),-1*S(i,j))\)

则:

令:\(A(x)=max(S(i,j),1\leq i\leq j\leq n),B(x)=max(-1*S(i,j),1\leq i\leq j\leq n)\)

则:\(max(|S(i,j)|,1\leq i\leq j\leq n=max(A(x),B(x))\)

显然\(A(x)\)是一个关于\(\mathit x\)的单调递减函数,\(B(x)\)是一个关于\(\mathit x\)的单调递增函数。

那么\(max(A(x),B(x))\)的最小值可以通过二分或者三分来解决:

1️⃣:三分解法:

\(C(x)=max(A(x),B(x))\),易知\(C(x)\)是一个凹函数,三分凹函数的极小值即可。

2️⃣:二分解法:

\(C(x)=B(x)-A(x)\),易知\(C(x)\)是一个单调递增的函数,二分出\(C(x)=0\)的点\(x_0\),

答案就是:\(Max(A(x_0),B(x_0))\)

代码:

三分:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <sstream>
#include <bitset>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-7
#define chu(x)  if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
int n;
int a[maxn];
double b[maxn];
double getv(double x)
{
    repd(i, 1, n)
    {
        b[i] = a[i] - x;
    }
    double res = 0;
    double sum = 0;
    repd(i, 1, n)
    {
        sum += b[i];
        res = max(res, sum);
        if (sum < 0)
            sum = 0;
    }
    sum = 0;
    repd(i, 1, n)
    {
        b[i] *= -1;
    }
    repd(i, 1, n)
    {
        sum += b[i];
        res = max(res, sum);
        if (sum < 0)
            sum = 0;
    }
    return res;
}
int main()
{
#if DEBUG_Switch
    freopen("C:\\code\\input.txt", "r", stdin);
#endif
    //freopen("C:\\code\\output.txt","r",stdin);
    n = readint();
    repd(i, 1, n)
    {
        a[i] = readint();
    }
    double low = *min_element(a + 1, a + 1 + n);
    double high = *max_element(a + 1, a + 1 + n);
    repd(rp, 1, 80)
    {
        double lmid = (low + low + high) / 3.000000;
        double rmid = (low + high + high) / 3.000000;
        double mv = getv(lmid);
        double mmv = getv(rmid);
        if (mv > mmv)
        {
            low = lmid;
        } else
        {
            high = rmid;
        }
    }
    printf("%.6f\n", min(getv(low), getv(high)) );
    return 0;
}

二分:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <sstream>
#include <bitset>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-7
#define chu(x)  if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
int n;
int a[maxn];
double b[maxn];
typedef pair<double, double > pdd;
pdd getv(double x)
{
    repd(i, 1, n)
    {
        b[i] = a[i] - x;
    }
    pdd res = mp(0, 0);
    double sum = 0;
    repd(i, 1, n)
    {
        sum += b[i];
        res.fi = max(res.fi, sum);
        if (sum < 0)
            sum = 0;
    }
    sum = 0;
    repd(i, 1, n)
    {
        b[i] *= -1;
    }
    repd(i, 1, n)
    {
        sum += b[i];
        res.se = max(res.se, sum);
        if (sum < 0)
            sum = 0;
    }
    return res;
}
int main()
{
#if DEBUG_Switch
    freopen("C:\\code\\input.txt", "r", stdin);
#endif
    //freopen("C:\\code\\output.txt","r",stdin);
    n = readint();
    repd(i, 1, n)
    {
        a[i] = readint();
    }
    double low = *min_element(a + 1, a + 1 + n);
    double high = *max_element(a + 1, a + 1 + n);
    double ans;
    repd(rp, 1, 40)
    {
        double mid = (low + high) / 2.000000;
        pdd res = getv(mid);
        if (res.fi > res.se)
        {
            ans = res.se;
            low = mid;
        } else
        {
            high = mid;
        }
    }
    printf("%.6f\n", ans);
    return 0;
}