codeforces#320(div2) E. Weakness and Poorness 三分
codeforces#320(div2) E. Weakness and Poorness 三分
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.
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 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.
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
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从-INF到INF的过程中,所求值是先减后增的,求最小值所以直接三分法。
虽然D题FST了,但是却学到了E题的三分法。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const ll INF=(1LL<<33); const double EPS=0.00000001; const int maxn=1000100; int n; double a[maxn],b[maxn],c[maxn]; double MaxLong(int op) { REP(i,1,n) c[i]=b[i]*op; double now=0,res=c[1]; REP(i,1,n){ if(now+c[i]>=0) now+=c[i]; else now=0; res=max(res,now); } return res; } double f(double x) { REP(i,1,n) b[i]=a[i]-x; //REP(i,1,n) cout<<b[i]<<" ";cout<<endl; return max(MaxLong(1),MaxLong(-1)); } double bin3(double l,double r) { while(l<r){ double m=(l+r)/2; double mm=(m+r)/2; //printf("%.2f %.2f %.2f %.2f\n",l,r,m,mm); double fm=f(m),fmm=f(mm); //printf("%.2f %.2f\n",fm,fmm); if(fabs(fm-fmm)<EPS) return fm; if(fm>fmm+EPS) l=m; else r=mm; } } int main() { freopen("in.txt","r",stdin); while(cin>>n){ REP(i,1,n) scanf("%lf",&a[i]); //printf("%.10f\n",f(5.375)); //REP(i,1,n) cout<<b[i]<<" ";cout<<endl; double ans=bin3(-1.0*INF,INF*1.0); printf("%.6f\n",ans); } return 0; }