Cod sursa(job #3350086)

Utilizator mircea_007Mircea Rebengiuc mircea_007 Data 5 aprilie 2026 12:02:24
Problema Euro Scor 55
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.8 kb
#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;

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; }
};

struct LiChao {
  int n;
  vec<Line> aint;
  LiChao( int n ): n(n), aint(2 * n - 1, Line()) {}
  void push( const Line &L ) { push( 0, 0, n - 1, L ); }
  void push( int root, int rl, int rr, Line L ) {
    int mij = (rl + rr) >> 1;
    if( L(mij) > aint[root](mij) )
      std::swap( L, aint[root] );
    if( rl == rr ) return;
    int state = 2 * int(L(rl) > aint[root](rl)) + int(L(rr) > aint[root](rr));
    if( state == 1 ) push( root + 2 * (mij+1 - rl), mij+1, rr, L );
    else if( state == 2 ) push( root + 1, rl, mij, L );
  }

  ll query( int idx ) const {
    ll ret = aint[0]( idx );
    int root = 0, rl = 0, rr = n - 1;
    while( rl < rr ){
      int mij = (rl + rr) >> 1;
      if( idx <= mij ) { root = + 1; rr = mij; }
      else { root = root + 2 * (mij+1 - rl); rl = mij + 1; }
      ret = std::max( ret, aint[root]( idx ) );
    }
    return ret;
  }
};

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]) }

  LiChao zile(n + 1);
  ll ret = 0;
  for( int i = 1; i <= n; i++ ){
    ret = sp[i] * (ll)i + zile.query( i ) - fee;
    zile.push( Line(ret, -sp[i]) );
  }

  fout << ret << std::endl;
  return 0;
}