三分 + 最大區間和
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.
InputThe 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).
OutputOutput a real number denoting the minimum possible weakness of a
3Output
1 2 3
1.000000000000000Input
4Output
1 2 3 4
2.000000000000000Input
10Output
1 10 2 9 3 8 4 7 5 6
4.500000000000000Note
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\n", ans); return 0; }
三分 + 最大區間和