Cod sursa(job #2716330)

Utilizator retrogradLucian Bicsi retrograd Data 5 martie 2021 00:38:45
Problema Euro Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.88 kb
	
#include <bits/stdc++.h>
 
using namespace std;
using ll = long long;
const ll INF = 2e18;
struct Line {
  ll a, b;
  ll Eval(ll x) { return a * x + b; }
};

struct ConvexTree {
  struct Node { Line line; int l = -1, r = -1; };
  vector<Node> T;
  int root = -1;
  const int MAX = 1e9; // Maximum abs(x)
  
  int update(int node, int b, int e, Line& upd) {
    if (node == -1) {
      T.push_back({upd});
      return T.size() - 1;
    }
    Line& cur = T[node].line;
    int m = (b + e) / 2, l = T[node].l, r = T[node].r;
    bool bb = upd.Eval(b) > cur.Eval(b);
    bool bm = upd.Eval(m) > cur.Eval(m);
    if (bm) swap(cur, upd);
    if (e - b == 1) { /* do nothing */ } 
    else if (bb != bm) l = update(l, b, m, upd);
    else r = update(r, m, e, upd);
    T[node].l = l; T[node].r = r;
    return node;
  }
  ll query(int node, int b, int e, int x) {
    if (node == -1) return -INF; // <= a * x + b for all lines
    int m = (b + e) / 2;
    return max(T[node].line.Eval(x), (x <= m 
      ? query(T[node].l, b, m, x)
      : query(T[node].r, m + 1, e, x)));
  }

  void InsertLine(Line l) { root = update(root, -MAX, MAX, l); } 
  ll EvalMax(int x) { return query(root, -MAX, MAX, 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
   
    ConvexTree 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;
}