Cod sursa(job #1989357)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 7 iunie 2017 01:09:24
Problema Euro Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.65 kb
#include <fstream>
#include <cmath>
#include <set>

using namespace std;

ifstream fin ("euro.in"); ofstream fout ("euro.out");

typedef long long i64;

const int nmax = 34570;
i64 d[nmax + 1];

struct dreapta {
    i64 a, b;

    dreapta() {}
    dreapta (i64 _a, i64 _b) {
        a = _a, b = _b;
    }

    inline bool operator < (const dreapta &x) const {
        if (b != x.b) return (b > x.b);
        return (a > x.a);
    }
};

set< dreapta > s;
set< dreapta >::iterator it;

long double intersect (dreapta d1, dreapta d2) { /// cand d2 il ia pe d1
    if (d1.a == d2.a) {
        return INFINITY;
    }

    long double x = (long double)(d2.b - d1.b) / (d1.a - d2.a);
    if (x < 0) return INFINITY;
    return x;
}

void baga (dreapta x) {
    if (s.find( x ) != s.end()) return ;

    set< dreapta >::iterator u = s.insert( x ).first;
    set< dreapta >::iterator top1, top2, last;

    top1 = u; last = u;

    if (u != s.begin()) {
        top2 = top1; -- top2;

        while (top1 != s.begin()) {
            top1 = top2;
            last = top1;
            if (top1 == s.begin()) {
                if (intersect(*top1, x) == INFINITY) {
                    s.erase( x );
                }
                break;
            }

            top2 = top1; -- top2;

            if (intersect(*top1, x) <= intersect(*top2, *top1)) {
                if (it == top1) -- it;
                s.erase(top1);
            } else {
                break;
            }
        }
    }

    top1 = last;
    top2 = last; ++ top2;

    if (top1 != s.end()) {
        while (top1 != s.end()) {
            top1 = top2;
            if (top1 == s.end()) break;

            ++ top2;
            if (top2 == s.end()) {
                if (intersect(*last, *top1) == INFINITY) {
                    s.erase(top1);
                }
                break;
            }

            if (intersect(*top1, *top2) <= intersect(*last, *top1)) {
                s.erase(top1);
            } else {
                break;
            }
        }
    }
}

int main() {
    int n, t;
    fin >> n >> t;

    s.insert(dreapta(0, 0));

    i64 sum = 0;
    for (int i = 1; i <= n; ++ i) {
        i64 x;
        fin >> x;

        sum += x;
        d[ i ] = (s.begin() -> a) * i + (s.begin() -> b) + sum * i - t;

        dreapta aux = dreapta(-sum, d[ i ]);
        baga( aux );

        while (s.size() > 1) {
            set< dreapta >::iterator it = s.begin();
            ++ it;

            if (intersect(*s.begin(), *it) < i + 1) {
                s.erase(s.begin());
            } else {
                break;
            }
        }
    }

    fout << d[ n ] << "\n";

    fin.close();
    fout.close();
    return 0;
}