Pagini recente » Cod sursa (job #406166) | Cod sursa (job #2067364) | Cod sursa (job #628459) | Cod sursa (job #1697230) | Cod sursa (job #2156661)
#include <bits/stdc++.h>
using namespace std;
using T = long long;
bool QUERY;
struct Line {
mutable T a, b, p;
T Eval(T x) const { return a * x + b; }
bool operator<(const Line& o) const {
return QUERY ? p < o.p : a < o.a;
}
};
struct LineContainer : multiset<Line> {
// for doubles, use kInf = 1/.0, div(a, b) = a / b
const T kInf = numeric_limits<T>::max();
T div(T a, T b) { // floored division
return a / b - ((a ^ b) < 0 && a % b); }
bool isect(iterator x, iterator y) {
if (y == end()) { x->p = kInf; return false; }
if (x->a == y->a) x->p = x->b > y->b ? kInf : -kInf;
else x->p = div(y->b - x->b, x->a - y->a);
return x->p >= y->p;
}
void InsertLine(T a, T b) {
auto nx = insert({a, b, 0}), it = nx++, pv = it;
while (isect(it, nx)) nx = erase(nx);
if (pv != begin() && isect(--pv, it)) isect(pv, it = erase(it));
while ((it = pv) != begin() && (--pv)->p >= it->p)
isect(pv, erase(it));
}
T EvalMax(T x) {
assert(!empty());
QUERY = 1; auto it = lower_bound({0,0,x}); QUERY = 0;
return it->Eval(x);
}
};
int main() {
freopen("euro.in", "r", stdin);
freopen("euro.out", "w", stdout);
int n, t;
cin >> n >> t;
// dp[i] = max_j(dp[j] + (gain[i] - gain[j]) * i - t)
// dp[i] = max_j(dp[j] - gain[j] * i + gain[i] * i - t)
// dp[i] = gain[i] * i - t + max_j(dp[j] - gain[j] * i)
// solution: keep stack of linear functions of type
// -gain[j] * X + dp[j]
// no monotony -> need set
LineContainer ct;
ct.InsertLine(0, 0);
long long ans = 0, gain = 0;
for (int i = 1; i <= n; ++i) {
int x; cin >> x; gain += x;
ans = ct.EvalMax(i) + gain * i - t;
ct.InsertLine(-gain, ans);
}
cout << ans << endl;
return 0;
}