Cod sursa(job #1269002)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 21 noiembrie 2014 19:11:00
Problema Euro Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.55 kb
#include <cmath>

#include <fstream>
#include <set>
#include <algorithm>

using namespace std;

typedef long long int64;

const double EPS = 1e-9;
const double oo = 1e15;

class Line {
  public:
    static const double QUERY_M = 1e17;

    double m, n;
    mutable double x;

    Line(const double _m, const double _n):
      m(_m),
      n(_n),
      x(oo) {}

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

    bool operator<(const Line &other) const {
        if (abs(other.m - QUERY_M) < EPS)
            return x < other.n;
        if (abs(m - other.m) < EPS)
            return n > other.n;
        return m < other.m;
    }
};

class LowerEnvelope: public multiset<Line> {
  public:
    void InsertLine(const Line &line) {
        iterator l = insert(line);
        if (Bad(l)) {
            erase(l);
            return;
        }
        while (l != begin() && Bad(prev(l)))
            erase(prev(l));
        while (next(l) != end() && Bad(next(l)))
            erase(next(l));
        if (l != begin())
            Update(prev(l));
        Update(l);
    }

    double MaxValue(const double x) const {
        return lower_bound(Line(Line::QUERY_M, x))->Value(x);
    }

  private:
    bool Bad(iterator y) const {
        if (y == end())
            return false;
        iterator z = next(y);
        if (y == begin()) {
            if (z == end())
                return false;
            return abs(y->m - z->m) < EPS && y->n - z->n < EPS;
        }
        iterator x = prev(y);
        if (z == end())
            return abs(x->m - y->m) < EPS && y->n - x->n < EPS;
        return (y->n - x->n) * (y->m - z->m) - (z->n - y->n) * (x->m - y->m) > -EPS;
    }

    void Update(iterator x) {
        if (x == end())
            return;
        iterator y = next(x);
        if (y == end())
            x->x = oo;
        else
            x->x = (y->n - x->n) / (x->m - y->m);
    }
};

inline int64 Round(const double value) {
    return int64(value + 0.5);
}

int main() {
    ifstream cin("euro.in");
    ofstream cout("euro.out");
    int n;
    int64 t, sum = 0, dp = 0;
    cin >> n >> t;
    LowerEnvelope envelope = LowerEnvelope();
    envelope.InsertLine(Line(0, 0));
    for (int i = 1; i <= n; ++i) {
        int64 value;
        cin >> value;
        sum += value;
        dp = Round(envelope.MaxValue(i)) + sum * i - t;
        envelope.InsertLine(Line(-sum, dp));
    }
    cout << dp << "\n";
    cin.close();
    cout.close();
    return 0;
}