Cod sursa(job #2716328)

Utilizator retrogradLucian Bicsi retrograd Data 5 martie 2021 00:13:54
Problema Euro Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.69 kb
	
#include <bits/stdc++.h>
 
using namespace std;
using ll = long long;
const ll INF = 2e18;

bool QUERY;
struct Line {
  mutable ll a, b, p;
  ll Eval(ll x) const { return a * x + b; }
  bool operator<(const Line& o) const {
    return QUERY ? p < o.p : a < o.a;
  }
};
struct LineContainer : multiset<Line> {
  ll div(ll a, ll b) { return a / b - (a % b < 0); }
  void InsertLine(ll a, ll b) {
    auto isect = [&](auto x, auto y) {
      if (y == end()) return x->p = INF, false;
      if (x->a == y->a) x->p = x->b > y->b ? INF : -INF;
      else x->p = div(x->b - y->b, y->a - x->a);
      return x->p >= y->p;
    };
    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));
  }
  ll EvalMax(ll 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;
}