Cod sursa(job #785360)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 8 septembrie 2012 16:54:37
Problema Avioane Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.47 kb
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cassert>

using namespace std;

typedef long long LL;

const int MaxN = 100005;
const int oo = 1000000000;

struct Line {
    LL m, n;

    Line() {
        m = n = 0;
    }

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

Line L[MaxN];
int N, V[MaxN], Best[MaxN];
int Top, S[MaxN];
LL Sol;

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

void BuildS() {
    for (int i = 1; i <= N; ++i) {
        L[i] = Line(1LL*V[i], -1LL*i*V[i]);
        for (; Top && Intersect(L[i], L[S[Top]]) <= Best[S[Top]]; --Top);
        if (!Top)
            Best[i] = 0;
        else
            Best[i] = Intersect(L[i], L[S[Top]]);
        S[++Top] = i;
    }
    Best[0] = oo, S[++Top] = 0;
}

void Solve() {
    sort(V+1, V+N+1);
    BuildS();
    for (int i = 1, j = 1; i <= N; ++i) {
        for (; Best[S[j+1]] <= i; ++j);
        Sol = max(Sol, 1LL*(N-i+1)*V[i]+L[S[j]].m*i+L[S[j]].n);
    }
}

void Read() {
    assert(freopen("avioane.in", "r", stdin));
    assert(scanf("%d", &N) == 1);
    for (int i = 1; i <= N; ++i)
        assert(scanf("%d", &V[i]) == 1);
}

void Print() {
    assert(freopen("avioane.out", "w", stdout));
    printf("%lld\n", Sol);
}

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