Pagini recente » Cod sursa (job #1940304) | Cod sursa (job #1201760) | Cod sursa (job #821219) | Cod sursa (job #231583) | Cod sursa (job #3350063)
#include <iostream>
#include <fstream>
#include <cassert>
#include <algorithm>
#include <vector>
#include <random>
template<class T> using vec = std::vector<T>;
using ll = long long;
constexpr ll INF = 1e18;
ll ceil( ll a, ll b ) {
if( a <= 0 ) return a / b;
return (a - 1) / b + 1;
}
struct Line {
ll ct, slope;
Line(): ct(0), slope(0) {}
Line( ll ct, ll slope ): ct(ct), slope(slope) {}
ll operator ()( ll x ) const { return ct + x * slope; }
ll overtake( const Line& that ) const {
if( slope == that.slope ) return +INF;
// ct + x * slope >= that.ct + x * that.slope
// x * (slope - that.slope) >= (that.ct - ct)
ll ret = ceil( that.ct - ct, slope - that.slope );
// assert( (*this)(ret) >= that(ret) );
// assert( (*this)(ret - 1) < that(ret - 1) );
return ret;
}
};
struct KinTour {
struct Node {
Line L;
ll overtake;
};
vec<Node> aint;
int aintn;
ll t;
KinTour( int n ): t(0) {
aintn = 1;
while( aintn < n ) aintn <<= 1;
aint.assign( 2 * aintn, Node{ Line(0, 0), +INF } );
}
void pull( int idx ) {
int left = idx * 2 + 1, right = idx * 2 + 2;
if( aint[left].L.ct < aint[right].L.ct )
std::swap( left, right );
if( aint[left].L.slope < aint[right].L.slope )
std::swap( left, right );
ll overtake = aint[left].L.overtake( aint[right].L );
if( overtake <= t ){
aint[idx].L = aint[left].L;
aint[idx].overtake = std::min( aint[left].overtake, aint[right].overtake );
}else{
aint[idx].L = aint[right].L;
aint[idx].overtake = std::min({ overtake, aint[left].overtake, aint[right].overtake });
}
}
void update( int idx, const Line &L ) {
idx += aintn - 1;
aint[idx].L = L;
while( idx )
pull( idx = (idx - 1) >> 1 );
}
ll query( ll new_t ) {
t = new_t;
while( aint[0].overtake <= t ){
int u = 0;
while( (aint[u * 2 + 1].overtake <= t || aint[u * 2 + 2].overtake <= t) ){
if( aint[u * 2 + 1].overtake <= t ) u = u * 2 + 1;
else u = u * 2 + 2;
}
pull( u );
while( u )
pull( u = (u - 1) >> 1 );
}
return aint[0].L(t);
}
};
int main() {
std::ifstream fin("euro.in");
std::ofstream fout("euro.out");
int n, fee;
fin >> n >> fee;
vec<int> costs(n);
for( int &x : costs ) fin >> x;
vec<ll> sp(n + 1, 0);
for( int i = 0; i < n; i++ )
sp[i + 1] = sp[i] + costs[i];
// dp[i] = -fee + max{ dp[j] + (sp[i] - sp[j]) * i }
// dp[i] = -fee + sp[i] * i + max{ (dp[j]) + i * (-sp[j]) }
KinTour zile(n + 1);
ll ret = 0;
for( int i = 1; i <= n; i++ ){
ret = sp[i] * (ll)i + zile.query( i ) - fee;
zile.update( i, Line(ret, -sp[i]) );
}
fout << ret << std::endl;
return 0;
}