Cod sursa(job #1165703)

Utilizator romircea2010FMI Trifan Mircea Mihai romircea2010 Data 2 aprilie 2014 20:56:34
Problema Avioane Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.96 kb
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

const int NMax = 100010;
const long long INF = 4000000000000000000LL;

int N;
int v[NMax];
long long ans;
int d[NMax];

void Read()
{
    ifstream f("avioane.in");
    f >> N;
    int newN = 0;
    for (int i = 1; i <= N; ++ i)
    {
        int x; f >> x;
        if (x > 0)
            v[++newN] = x;
    }
    N = newN;
    f.close();
}

long long Better(const int i, const int j)
{
    /// returneaza numarul minim  de zile dupa care faptul de a lua ca pret de bilet de economy al j-lea pret
    /// este mai bine decat al lua pe al i-lea;
    if (v[i] == v[j])
        return INF;
    if (1LL * v[i] * (j - i + 1) < 1LL * v[j])
        return -INF;
    return ((1LL * v[i] * (j - i + 1) - v[j]) / (v[j] - v[i])) + ((abs(1LL * v[i] * (j - i + 1) - v[j]) % (v[j] - v[i])) ? 1LL : 0LL);
}

inline long long Cost(const int i, const int j)
{
    /// returneaza costul total daca as alege ca pret de economy pretul i si ca pret de business pretul j
    return 1LL * v[j] * (N - j + 1) + 1LL * v[i] * (j - i);
}

void Solve()
{
    sort (v + 1, v + N + 1);
    ans = max(ans, Cost(1, 2));
    int st, dr;
    st = dr = 1;
    d[1] = 1;
    for (int i = 3; i <= N; ++ i)
    {
        ans = max(ans, Cost(d[st], i));
        while ((st < dr && 1LL * d[st+1] + Better(d[st], d[st+1]) <= 1LL * i - 1LL))
        {
            /// scot acolo bilete din varful deque-ului care nu mai sunt bune fata de cele din dreapta
            /// adica daca d[st+1] ar fi biletul de economy si mi-ar face pana la ziua i - 1 (inclusiv)
            /// un cost mai bun (sau egal) cu costul pe care il face d[st] pana la a ziua i - 1(inclusiv)
            /// atunci scot d[st]
            ++ st;
            ans = max(ans, Cost(d[st], i));
        }
        if (v[i - 1] != v[dr] || st > dr)
        {
            /// if este ca nu are sens sa iau in considerare un pret de economy pe pozitia i - 1 pentru ca
            /// clar costul este mai bun pentru cel de pe pozitia dr cu dr < i - 1 pentru ca are mai multe zile pe care
            /// le acopera. deci nu bag deloc in deque pe i - 1;
            while ((dr > st && Better(d[dr],  i - 1) <= Better(d[dr - 1], d[dr])) || (dr == st && Better(d[dr], i - 1) + 1LL * (i - 1) <= 1LL * (i - 1)))
            {
                /// daca timpul in care se face i - 1 mai bun fata de d[dr] este mai mic decat timpul in care
                /// se face d[dr] mai bun decat d[dr - 1] atunci ii clar ca i - 1 o sa fie mai bun ca d[dr]
                /// atunci ii clar ca d[dr] nu va fi niciodata bun si deci il elimin
                --dr;
            }
            d[++dr] = i - 1;
        }
        if (st <= dr)
            ans = max(ans, Cost(d[st], i));
    }

}

void Write()
{
    ofstream g("avioane.out");
    g << ans << "\n";
    g.close();
}

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