Cod sursa(job #847482)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 4 ianuarie 2013 00:09:06
Problema Euro Scor 30
Compilator cpp Status done
Runda Lista lui wefgef Marime 1.74 kb
#include <cstdio>
#include <cmath>
#include <cassert>
#include <deque>
#include <algorithm>

using namespace std;

typedef long long LL;

const int MaxN = 50000;
const LL oo = 1LL<<60;

struct Line {
    LL m, n;

    Line() {}

    Line(const LL m, const LL n) {
        this->m = m, this->n = n;
    }

    LL Value(const LL x) const {
        return m * x + n;
    }

    static LL Intersect(const Line &L1, const Line &L2) {
        if (L1.m > L2.m)
            return oo;
        if (L1.m == L2.m)
            return L1.n < L2.n ? 0 : oo;
        return static_cast<int>(ceil(1.0 * (L2.n - L1.n) / (L1.m - L2.m)));
    }
};

Line L[MaxN];
int N;
LL T, Sum[MaxN], DP[MaxN], Best[MaxN];
deque<int> Deq;

void PrintDeq() {
    for (size_t i = 0; i < Deq.size(); ++i)
        fprintf(stderr, "%d ", Deq[i]);
    fprintf(stderr, "\n");
}

void Solve() {
    L[0] = Line(0, 0);
    Deq.push_back(0);
    for (int i = 1; i <= N; ++i) {
        for (; Deq.size() > 1 && Best[Deq[1]] <= i; Deq.pop_front());
        DP[i] = L[Deq.front()].Value(i) + Sum[i] * i - T;
        L[i] = Line(-Sum[i], DP[i]);
        for (; Deq.size() > 1 && Line::Intersect(L[Deq.back()], L[i]) <= Best[Deq.back()]; Deq.pop_back());
        Best[i] = Line::Intersect(L[Deq.back()], L[i]);
        Deq.push_back(i);
        PrintDeq();
    }
}

void Read() {
    assert(freopen("euro.in", "r", stdin));
    assert(scanf("%d %lld", &N, &T) == 2);
    for (int i = 1; i <= N; ++i) {
        assert(scanf("%lld", &Sum[i]) == 1);
        Sum[i] += Sum[i - 1];
    }
}

void Print() {
    assert(freopen("euro.out", "w", stdout));
    printf("%lld\n", DP[N]);
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}