Cod sursa(job #1307294)

Utilizator geniucosOncescu Costin geniucos Data 1 ianuarie 2015 20:37:09
Problema Euro Scor 45
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.16 kb
#include<cstdio>
#include<vector>
#include<set>

using namespace std;

int N, T, S[40000], a[40000];
long long dp[40000];
vector < pair < double, double > > sir;

double eps = 1e-6;
double oo = 1e15;
double Query_A = 1e17;

double mod (double x)
{
    if (x < 0) return -x;
    return x;
}

class line
{
    public:
    double A, B;
    mutable double x;
    line (double A, double B)
    {
        this->A = A;
        this->B = B;
        this->x = oo;
    }

    double val (double x) const
    {
        return (double) A * x + B;
    }

    bool operator < (const line &other) const
    {
        if ( mod (other.A - Query_A) < eps )
            return x < other.B;
        if ( mod (other.A - A) < eps)
            return B > other.B;
        return A < other.A;
    }
};

class Batch : public multiset < line >
{
    public:
    void Insert (line curr)
    {
        iterator it = insert (curr);
        if (Bad (it))
        {
            erase (it);
            return ;
        }
        while (it != begin() && Bad (prev (it)))
            erase (prev (it));
        while (next (it) != end() && Bad (next (it)))
            erase (next (it));
        Refresh (it);
        if (it != begin()) Refresh (prev(it));
    }

    double Query (double X)
    {
        return lower_bound ( line (Query_A, X) ) -> val (X);
    }

    private:
    iterator next (iterator x)
    {
        iterator y = x;
        y ++;
        return y;
    }

    iterator prev (iterator x)
    {
        iterator y = x;
        y --;
        return y;
    }

    bool Bad (iterator y)
    {
        if (y == end())
            return 0;
        iterator z = next (y);
        if (y == begin())
        {
            if (z == end())
                return 0;
            return mod (y->A - z->A) < eps && y->B - z->B < eps;
        }
        iterator x = prev (y);
        if (z == end())
            return mod (y->A - x->A) < eps && y->B - x->B < eps;
        return (y->B - x->B) * (y->A - z->A) - (z->B - y->B) * (x->A - y->A) > -eps;
    }

    void Refresh (iterator x)
    {
        if (x == end())
            return ;
        iterator y = next (x);
        if (y == end())
            x->x = oo;
        else
            x->x = (y->B - x->B) / (x->A - y->A);
    }
}smen;

long long get_integer (double x)
{
    return (long long) ( (double) x + 0.5 );
}

void brut_insert (pair < double, double > X)
{
    sir.push_back (X);
}

double brut_query (double x)
{
    double maxx = -oo;
    for (vector < pair < double , double > > :: iterator it = sir.begin(); it != sir.end(); it ++)
        if ( (double) x * it->first + it->second > maxx)
            maxx = (double) x * it->first + it->second;
    return maxx;
}

int main()
{
freopen ("euro.in", "r", stdin);
freopen ("euro.out", "w", stdout);

scanf ("%d %d", &N, &T);

for (int i=1; i<=N; i++)
{
    scanf ("%d", &a[i]);
    S[i] = S[i-1] + a[i];
}

for (int i=1; i<=N; i++)
{
    dp[i] = (long long) get_integer (smen.Query (i)) + 1LL * i * S[i] - T;
    smen.Insert (line (-S[i], dp[i]));
}

printf ("%lld\n", dp[N]);

return 0;
}