Cod sursa(job #1971242)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 20 aprilie 2017 00:48:30
Problema Euro Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.73 kb
#include <bits/stdc++.h>

using namespace std;

const int nmax = 1e5 + 10;
const long double inf = 1e18;

struct line {
    long long A, B;
    mutable long double X;

    line() {
        A = B = 0; X = 0;
    }

    line(long long A, long long B) {
        this -> A = A; this -> B = B; X = 0;
    }

    line(long double X) {
        this -> A = this -> B = 0; this -> X = X;
    }

    long long val(int x) const {
        return this -> A * x + this -> B;
    }

    static bool slope_comparator;
    bool operator < (const line other) const {
        if (!slope_comparator)
            return this -> X < other.X;

        if (this -> A == other.A)
            return this -> B < other.B;
        return this -> A < other.A;
    }

    long double intersect(const line other) const {
        return 1.0L * (other.B - this -> B) / (this -> A - other.A);
    }
};
bool line :: slope_comparator = 1;

///Convex Hull Trick
struct cht {
    multiset < line > m;

    void _insert(const line &curr) {
        multiset < line > :: iterator it;

        it = m.insert(curr);
        if (bad(it)) {
            m.erase(it);
            return;
        }

        while (it != m.begin() && bad(prev(it)))
            m.erase(prev(it));
        while (next(it) != m.end() && bad(next(it)))
            m.erase(next(it));

        _update(it);
        if (it != m.begin())
            _update(prev(it));
    }

    long long _query(int x) {
        line :: slope_comparator = 0;
        auto it = m.lower_bound(line(x));
        line :: slope_comparator = 1;

        return it -> val(x);
    }

    bool bad(multiset < line > :: iterator it) {
        auto nxt = next(it);
        if (nxt == m.end())
            return 0;
        if (it -> A == nxt -> A)
            return 0;

        if (it == m.begin())
            return 0;
        auto prv = prev(it);

        return prv -> intersect(*it) >= it -> intersect(*nxt);
    }

    void _update(multiset < line > :: iterator it) {
        auto nxt = next(it);
        if (nxt == m.end()) it -> X = inf;
        else it -> X = it -> intersect(*nxt);
    }
} B;

int n, commission;
int a[nmax];
long long dp[nmax];

void input() {
    scanf("%d %d", &n, &commission);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        a[i] += a[i-1];
    }
}

void get_answer() {
    for (int i = 1; i <= n; ++i) {
        B._insert(line(-a[i-1], dp[i-1]));
        dp[i] = 1LL * a[i] * i + B._query(i) - commission;
    }
}

void output() {
    printf("%lld\n", dp[n]);
}

int main()
{
    freopen("euro.in","r",stdin);
    freopen("euro.out","w",stdout);

    input();
    get_answer();
    output();

    return 0;
}