Weakness and Poorness
Weakness and Poorness
- standard input
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.
Sample test(s)
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的递增,形成一个凹函数;
其次,求取连续序列 最大和 与连续序列最小和的 绝对值 :
求连续序列最大和:
设 b[i] = a[i] - x,sum(b[i]) = 连续序列中有 b[i] 的 序列最大和;
若sum(b[j-1])<0,那么sum(b[j]) = max( b[j],b[j] + sum(b[j-1]) ),sum(b[j])必然等于b[j],这时sum(b[j])只加 自身 为最优;
同理,求连续序列最小和,若sum(b[j-1]) > 0;sum(b[j]) = b[j];
至于卡精度的问题,我还是渣渣= =!,大神求教!
复杂度 O(n*log(n))
#include<cstdio> #include<algorithm> const double eps = 1e-6; using namespace std; int n; double a[200005]; double b[200005]; double fabs(double x){ if(x<0)return -x; return x; } double work(double x){ for(int i = 0; i < n; i++) b[i] = a[i] - x; double sum = 0; double ans = 0; for(int i = 0; i < n; i++){ sum += b[i]; if(sum < 0) sum = 0; ans = max(ans,sum); } sum = 0; for(int i = 0; i < n; i++){ sum += b[i]; if(sum > 0) sum = 0; ans = max(fabs(sum),ans); } return ans; } int main(){ scanf("%d",&n); for(int i = 0; i < n; i++){ scanf("%lf",&a[i]); } double l = -10000; double r = 10000; for(int i = 0; i < 100; i++){ double lmid = (l+r)/2; double rmid = (lmid+r)/2; if(work(lmid) > work(rmid)) l = lmid; else r = rmid; } printf("%.6f\n",work(l)); return 0; }