#include #include #include const int MAXN = 100010; struct Point { __int64 x, y; }point[MAXN], high[2][MAXN], low[2][MAXN], merge[MAXN * 2]; int pointNumber, highNumber[2], lowNumber[2], mergeNumber; int n, stack[MAXN], top; __int64 a[MAXN]; Point operator + (const Point &a, const Point &b) { Point r; r.x = a.x + b.x; r.y = a.y + b.y; return r; } Point operator - (const Point &a, const Point &b) { Point r; r.x = a.x - b.x; r.y = a.y - b.y; return r; } inline __int64 operator * (const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; } inline __int64 absolute(int x) { return x >= 0 ? x : -x; } inline double max(const double &x, const double &y) { return x > y ? x : y; } inline __int64 cross(const Point &a, const Point &b, const Point &o) { return (a - o) * (b - o); } void getBound(Point result[], int &resultNumber, bool isHigh) { if(pointNumber == 1) { result[0] = point[0]; resultNumber = 1; return; } stack[0] = 0; stack[1] = 1; top = 2; if(isHigh) { for(int i=2;i= 2 && cross(point[stack[top-2]], point[i], point[stack[top-1]]) < 0) { -- top; } stack[top++] = i; } } else { for(int i=2;i= 2 && cross(point[stack[top-2]], point[i], point[stack[top-1]]) > 0) { -- top; } stack[top++] = i; } } resultNumber = top; for(int i=0;i 0) { merge[mergeNumber++] = temp1; ++ pNum1; } else { merge[mergeNumber++] = temp2; ++ pNum2; } } } } } double solve(int l, int r) { if(l == r) { return absolute(a[l]); } int mid = (l + r) >> 1; double ansL = solve(l, mid); double ansR = solve(mid + 1, r); double ans = max(ansL, ansR); __int64 sum = 0; pointNumber = 0; for(int i=mid;i>=l;--i) { sum += a[i]; point[pointNumber].x = mid - i + 1; point[pointNumber].y = sum; ++ pointNumber; } getBound(high[0], highNumber[0], true); getBound(low[0], lowNumber[0], false); sum = 0; pointNumber = 0; for(int i=mid+1;i<=r;++i) { sum += a[i]; point[pointNumber].x = i - mid; point[pointNumber].y = sum; ++ pointNumber; } getBound(high[1], highNumber[1], true); getBound(low[1], lowNumber[1], false); mergeNumber = 0; mergeBound(high[0], highNumber[0], high[1], highNumber[1], true); mergeBound(low[0], lowNumber[0], low[1], lowNumber[1], false); for(int i=0;i