Cod sursa(job #1949355)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 1 aprilie 2017 22:56:44
Problema Euro Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.46 kb
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <set>

using namespace std;

typedef long long int lint;

struct Line {
    int A;
    lint B;

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

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

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

    friend long double intersect(const Line &a, const Line &b) {
        return 1.0L * (- a.B + b.B) / (a.A - b.A);
    }
};

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

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

    lint query(int x) {
        while (1) {
            iterator it = next(begin());
            if (it == end())
                break;

            if (x >= intersect(*begin(), *it))
                erase(begin());
            else
                break;
        }

        return begin() -> 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);
    }
} batch;

const int NMAX = 35000 + 5;

int N = 20000, T = 100;
int sp[NMAX];
lint dp[NMAX];

/*lint dp2[NMAX];
void bruteDp() {
    for (int i = 1; i <= N; ++ i) {
        dp2[i] = dp2[i - 1] + i * (sp[i] - sp[i - 1]) - T;
        for (int j = 0; j < i; ++ j)
            dp2[i] = max(dp2[i], dp2[j] - T + 1LL * (sp[i] - sp[j]) * i);
    }
}*/

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

    cin >> N >> T;

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

    //bruteDp();
    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 << dp2[N] << '\n';
    cout << dp[N] << '\n';
    return 0;
}