Cod sursa(job #2513870)

Utilizator Alex_BubBuburuzan Alexandru Alex_Bub Data 23 decembrie 2019 22:48:31
Problema Euro Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.19 kb
#include <fstream>
#include <cmath>
#include <stack>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

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

const long long NMax = 34567, oo = LLONG_MAX;
long long N, V[NMax + 5], S[NMax + 5], T, sqrtN, NrBuckets, DP[NMax + 5];

struct bucket
{
    vector< pair<long long, long long> > Line;
    stack <long long> Hull;
    long long Stop[200], low, hi;
}
Bucket[200];

long long Intersect(pair<long long, long long> L1, pair<long long, long long> L2)
{
    if(L1.first == L2.first)
        return -oo;

    return (L1.second - L2.second) / (L2.first - L1.first);
}

inline bool compare(pair<long long, long long> A, pair<long long, long long> B)
{
    return A > B;
}

void CreateHull(bucket & B)
{
    sort(B.Line.begin(), B.Line.end(), compare);

    B.Stop[0] = oo;
    B.Hull.push(0);

    for(long long i = 1; i < B.Line.size(); i++)
    {
        while(Intersect(B.Line[B.Hull.top()], B.Line[i]) > B.Stop[B.Hull.top()])
            B.Hull.pop();

        B.Stop[i] = Intersect(B.Line[B.Hull.top()], B.Line[i]);
        B.Hull.push(i);
    }
}

long long Query(bucket & B, long long x)
{
    while(x > B.Stop[B.Hull.top()])
        B.Hull.pop();

    pair <long long, long long> line = B.Line[B.Hull.top()];
    return line.first * x + line.second;
}

int main()
{
    fin >> N >> T;
    sqrtN = sqrt(N);

    for(long long i = 1; i <= N; i++)
    {
        fin >> V[i];
        S[i] = V[i] + S[i - 1];

        /// DP[i] = (-S[j] * i + DP[j] ) + (S[i] * i - T), j < i

        for(long long k = 1; k <= NrBuckets; k++)
            DP[i] = max(DP[i], Query(Bucket[k], i));

        for(auto line : Bucket[NrBuckets + 1].Line)
            DP[i] = max(DP[i], line.first * i + line.second);

        DP[i] += S[i] * i - T;
        Bucket[NrBuckets + 1].Line.push_back({-S[i], DP[i]});

        if(i % sqrtN == 0)
        {
            NrBuckets++;
            Bucket[NrBuckets].low = i - sqrtN + 1, Bucket[NrBuckets].hi = i;
            CreateHull(Bucket[NrBuckets]);
        }
    }
    fout << DP[N] << '\n';

    fin.close();
    fout.close();

    return 0;
}