Cod sursa(job #1949189)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 1 aprilie 2017 19:59:58
Problema Euro Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.56 kb
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <set>

using namespace std;

const long double INF = 1E18;
typedef long long int lint;

struct Line {
    int A;
    lint B;
    mutable double x;

    Line(int _A, lint _B):
        A(_A), B(_B), x(INF) {}

    Line(long double _x = 0):
        A(-1), B(-1), x(_x) {}

    lint getVal(int _x) const {
        return 1LL * A * _x + B;
    }

    static bool slopeCompare;
    friend bool operator<(const Line &a, const Line &b) {
        if (slopeCompare) {
            if (a.A != b.A)
                return a.A < b.A;
            else
                return a.B < b.B;
        }
        else
            return a.x < b.x;
    }

    friend long double intersect(const Line &a, const Line &b) {
        return (a.B - b.B) / (a.A - b.A);
    }
};
bool Line :: slopeCompare = true;

class Batch : set <Line> {
public:
    void Insert(const Line &l) {
        iterator it = insert(l).first;
        if (bad(it)) {
            erase(it);
            return ;
        }

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

        refresh(it);
        if (it != begin())
            refresh(prev(it));
    }

    lint query(lint x) {
        Line :: slopeCompare = false;
        iterator it = lower_bound(Line(x));
        Line :: slopeCompare = true;

        return it -> getVal(x);
    }

private:
    bool bad(iterator it) {
        iterator nxt = next(it);
        if (nxt == end())
            return false;
        if (nxt -> A == it -> A)
            return true;

        if (it == begin())
            return false;
        iterator prv = prev(it);

        return intersect(*prv, *nxt) >
                intersect(*it, *nxt);
    }

    void refresh(iterator it) {
        iterator nxt = next(it);
        if (nxt == end())
            it -> x = INF;
        else
            it -> x = intersect(*it, *nxt);
    }
} batch;

const int NMAX = 35000 + 5;

int sp[NMAX];
lint dp[NMAX];

int main()
{
    ifstream cin("euro.in");
    ofstream cout("euro.out");

    int N = 1000, T = 5;
    cin >> N >> T;

    for (int i = 1; i <= N; ++ i) {
        cin >> sp[i];
        //sp[i] = rand() % 200 - 100;
        sp[i] += sp[i - 1];
    }

    for (int i = 1; i <= N; ++ i) {
        batch.Insert(Line(-sp[i - 1], dp[i - 1]));
        dp[i] = 1LL * sp[i] * i - T + batch.query(i);
    }

    cout << dp[N] << '\n';
    return 0;
}