Pagini recente » Cod sursa (job #1285251) | Cod sursa (job #3138575) | Cod sursa (job #2053250) | Cod sursa (job #1304569) | Cod sursa (job #1853293)
#include <bits/stdc++.h>
using namespace std;
typedef int64_t i64;
const int NMAX = 35000;
const i64 inf = 1e18;
const long double eps = 1e-12;
int N, T;
int curr;
i64 sum[NMAX];
i64 DP[NMAX];
long double X[NMAX];
int getSign(long double value) {
if (value >= -eps && value <= eps)
return 0;
if (value < -eps)
return -1;
return 1;
}
i64 doubleToInt(long double value) {
int sgn = getSign(value);
if (sgn == 0)
return 0;
if (sgn > 0)
return value + 0.5;
return value - 0.5;
}
struct Line {
i64 m, n;
int pos;
Line(i64 m = 0, i64 n = 0, int pos = 0):
m(m), n(n), pos(pos) {
}
bool operator<(const Line &rhs) const {
return m < rhs.m ? 1 : (m > rhs.m ? 0 : n < rhs.n);
}
long double xIntersect(const Line &rhs) const {
if (m == rhs.m)
return inf;
return (long double)(rhs.n - n) / (long double)(m - rhs.m);
}
i64 getValue(int x) {
return m * x + n;
}
} Lines[NMAX];
set<Line> convexHullTrick;
set<pair<long double, i64>> xIntervals;
bool Check(set<Line>::iterator y) {
set<Line>::iterator x = prev(y), z = next(y);
if (y == convexHullTrick.begin() || z == convexHullTrick.end())
return 0;
i64 xyIntersect = x->xIntersect(*y);
i64 xzIntersect = x->xIntersect(*z);
if (xzIntersect <= xyIntersect)
return 1;
return 0;
}
void Update(set<Line>::iterator y) {
xIntervals.erase({X[y->pos], y->pos});
if (y == convexHullTrick.begin()) {
X[y->pos] = -inf;
xIntervals.insert({-inf, y->pos});
} else {
set<Line>::iterator x = prev(y);
X[y->pos] = x->xIntersect(*y);
xIntervals.insert({X[y->pos], y->pos});
}
}
void addLine(i64 m, i64 n) {
Lines[curr] = Line(m, n, curr);
set<Line>::iterator y = convexHullTrick.insert(Lines[curr++]).first;
set<Line>::iterator z = next(y);
if (z != convexHullTrick.end() && y->m == z->m) {
convexHullTrick.erase(y);
return;
}
set<Line>::iterator x = prev(y);
if (y != convexHullTrick.begin() && x->m == y->m) {
xIntervals.erase({X[x->pos], x->pos});
convexHullTrick.erase(x);
Update(y);
}
if (Check(y)) {
convexHullTrick.erase(y);
return;
}
while (next(y) != convexHullTrick.end() && Check(next(y))) {
xIntervals.erase({X[next(y)->pos], next(y)->pos});
convexHullTrick.erase(next(y));
}
while (y != convexHullTrick.begin() && Check(prev(y))) {
xIntervals.erase({X[prev(y)->pos], prev(y)->pos});
convexHullTrick.erase(prev(y));
}
if (next(y) != convexHullTrick.end())
Update(next(y));
Update(y);
}
int main() {
assert(freopen("euro.in", "r", stdin));
assert(freopen("euro.out", "w", stdout));
int i;
cin >> N >> T;
for (i = 1; i <= N; ++i) {
int value;
cin >> value;
sum[i] = sum[i - 1] + value;
}
for (i = 1; i <= N; ++i) {
set<pair<long double, i64>>::iterator it = xIntervals.lower_bound({i, -inf});
int lineIndex = -1;
if (xIntervals.size()) {
if (it == xIntervals.end()) {
--it;
lineIndex = it->second;
} else if (i >= it->first) {
lineIndex = it->second;
} else {
--it;
lineIndex = it->second;
}
}
DP[i] = sum[i] * i - T;
if (lineIndex != -1)
DP[i] = max(DP[i], Lines[lineIndex].getValue(i) + sum[i] * i - T);
addLine(-sum[i], DP[i]);
}
cout << DP[N] << '\n';
return 0;
}