Cod sursa(job #2043430)

Utilizator retrogradLucian Bicsi retrograd Data 19 octombrie 2017 23:49:12
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.95 kb
#include <vector>
#include <iostream>
#include <queue>
#include <set>
#include <cassert>
#include <limits>
#include <algorithm>
#include <map>
  
using namespace std;
  
struct Line {
    long long a, b;
    long long Eval(int x) {
        return a * x + b;
    }
};

struct ConvexTree {
    vector<Line> T;

    ConvexTree(int n) : T(4 * n, Line{0, (long long)-1e18}) {}
    
    void Update(int node, int b, int e, Line now) {
        Line& cur = T[node];
        if (cur.Eval(b) > now.Eval(b) && cur.Eval(e) > now.Eval(e)) return;
        if (cur.Eval(b) < now.Eval(b) && cur.Eval(e) < now.Eval(e)) {
            cur = now; return;
        }
        int m = (b + e) / 2;
        if (cur.Eval(b) < now.Eval(b)) swap(cur, now);
        if (cur.Eval(m) > now.Eval(m))
            Update(node * 2 + 1, m + 1, e, now);
        else {
            swap(cur, now);
            Update(node * 2, b, m, now);
        }
    }

    long long EvalMax(int node, int b, int e, int x) {
        if (b == e) return T[node].Eval(x);
        int m = (b + e) / 2;
        long long ans = T[node].Eval(x);
        if (x <= m) ans = max(ans, EvalMax(node * 2, b, m, x));
        else ans = max(ans, EvalMax(node * 2 + 1, m + 1, e, x));
        return ans;
    }
};
   
  
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(n + 1);
    ct.Update(1, 0, n, Line{0, 0});
  
    long long ans = 0, gain = 0;
    for (int i = 1; i <= n; ++i) {
        int x; cin >> x; gain += x;
        ans = ct.EvalMax(1, 0, n, i) + gain * i - t;
        ct.Update(1, 0, n, Line{-gain, ans});
    }
    cout << ans << endl;
    return 0;
}