Pagini recente » Cod sursa (job #505196) | Cod sursa (job #2243904) | Borderou de evaluare (job #1888049) | Cod sursa (job #2508014) | Cod sursa (job #2707923)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 2e18;
struct Line { ll a, b; };
ll Floor(ll a, ll b) { return a / b - (a % b < 0); }
ll Ceil(ll a, ll b) { return a / b + (a % b > 0); }
struct KinTour {
struct Node { int dp = 0; ll ev = INF; };
int n; ll t = -INF;
vector<Node> T; vector<Line> L;
KinTour(int n) : n(n), T(2 * n), L(n, Line{0, 0}) {}
ll eval(int i) { return L[i].a * t + L[i].b; }
ll inter(int i, int j) {
// assert(eval(i) >= eval(j));
if (L[i].a >= L[j].a) return INF;
return Ceil(L[i].b - L[j].b, L[j].a - L[i].a);
}
void go(int x, int b, int e, int pos) {
if ((e <= pos || b > pos) && T[x].ev > t) return;
if (e - b == 1) { T[x].dp = b; return; }
int m = (b + e) / 2, z = x + 2 * (m - b);
go(x + 1, b, m, pos); go(z, m, e, pos);
int i = T[x + 1].dp, j = T[z].dp;
if (eval(i) < eval(j)) swap(i, j);
T[x].dp = i; T[x].ev = min({T[x + 1].ev, T[z].ev, inter(i, j)});
}
ll EvalMax(ll t) {
assert(this->t <= t);
this->t = t; go(1, 0, n, -1);
return eval(T[1].dp);
}
void Update(int i, Line l) {
L[i] = l; go(1, 0, n, i);
}
};
int main() {
ifstream cin("euro.in");
ofstream cout("euro.out");
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
ll ans = 0, gain = 0;
KinTour kt(n + 1);
for (int i = 1; i <= n; ++i) {
int x; cin >> x; gain += x;
ans = kt.EvalMax(i) + gain * i - t;
kt.Update(i, Line{-gain, ans});
}
cout << ans << endl;
return 0;
}