Cod sursa(job #1662722)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 24 martie 2016 23:42:30
Problema Avioane Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.82 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define line pair<int, int>
#define ll long long
#define mp make_pair
#define pb push_back
#define slope first
#define delta second

using namespace std;

ifstream in("avioane.in");
ofstream out("avioane.out");

inline int cmp_double(const double &a, const double &b) {
    if(a - b < -1e-6) return -1;
    if(a - b > 1e-6) return 1;
    return 0;
}

inline bool cmp_line(const line &a, const line &b) {
    if(a.delta == b.delta) return a.slope > b.slope;
    return a.delta < b.delta;
}

inline double inters_time(const line &a, const line &b) {
    if(a.slope == b.slope && a.delta > b.delta) return 1e12;
    else if(a.slope <= b.slope && a.delta <= b.delta) return 0.0;
    return 1.0 * (a.delta - b.delta) / (b.slope - a.slope);
}

int main() {
    int n;

    in >> n;

    vector<int> vec(n, 0);
    vector<int> stk(n, 0);
    vector<line> lin(n, mp(0, 0));

    for(int i = 0; i < n; i++) in >> vec[i];
    sort(begin(vec), end(vec));

    int _left = 0, _right = -1;
    ll best_profit = 1ll * vec[0] * n;
    for(int i = 0; i < n - 1; i++) {
        lin[i] = mp(vec[i], -(i+1)*vec[i]);
        while(_left < _right && cmp_double(inters_time(lin[stk[_left]], lin[stk[_left + 1]]), i) <= 0) {
            _left++;
        }
        while(_right > _left && cmp_double(inters_time(lin[stk[_right - 1]], lin[stk[_right]]),
                                           inters_time(lin[stk[_right]], lin[i])) >= 0) {
            _right--;
        }
        stk[++_right] = i;
        const ll first_class = 1ll * (n - i - 1) * vec[i + 1];
        const ll second_class = 1ll * (i + 1 - stk[_left]) * vec[stk[_left]];
        best_profit = max(best_profit, first_class + second_class);
    }

    out << best_profit << '\n';
    return 0;
}