Cod sursa(job #2156645)

Utilizator retrogradLucian Bicsi retrograd Data 8 martie 2018 21:33:04
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.87 kb
#include <bits/stdc++.h>

using namespace std;


using T = long long;
const T is_query = numeric_limits<T>::min();
 
struct Line {
    T a, b;
    mutable function<const Line *()> succ;
    
    T Eval(T x) const { return a * x + b; }
    
    bool operator<(const Line &rhs) const {
        if (rhs.b != is_query) return a < rhs.a;
        const Line *s = succ();
        if (!s) return 0;
        return Eval(rhs.a) < s->Eval(rhs.a);
    }
};
 
struct ConvexSet : public multiset<Line> {
    bool bad(iterator y) {
        auto z = next(y);
        if (y == begin()) {
            return (z == end() ? 0 : y->a == z->a && y->b <= z->b);
        }
        auto x = prev(y);
        if (z == end()) return y->a == x->a && y->b <= x->b;
        return (x->b - y->b) * (z->a - y->a) >= (y->b - z->b) * (y->a - x->a);
    }
 
    void InsertLine(T a, T b) {
        auto y = insert({a, b});
        y->succ = [=] { return next(y) == end() ? 0 : &*next(y); };
        if (bad(y)) { erase(y); return; }
        while (next(y) != end() && bad(next(y))) erase(next(y));
        while (y != begin() && bad(prev(y))) erase(prev(y));
    }
 
    T Eval(T x) { return lower_bound({x, is_query})->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
   
    ConvexSet 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.Eval(i) + gain * i - t;
        ct.InsertLine(-gain, ans);
    }
    cout << ans << endl;
    return 0;
}