Cod sursa(job #2737381)

Utilizator AlexPop28Pop Alex-Nicolae AlexPop28 Data 4 aprilie 2021 18:27:38
Problema Euro Scor 100
Compilator cpp-64 Status done
Runda Lista lui wefgef Marime 1.73 kb
#include <bits/stdc++.h>
#define dbg() cerr <<
#define name(x) (#x) << ": " << (x) << ' ' <<
// mhm o sa o corectez azi oare?

using namespace std;

struct Line {
  int64_t a, b;
  Line(int64_t a_, int64_t b_) : a(a_), b(b_) {}
  int64_t operator()(const int64_t &x) const { return a * x + b; }
  bool operator<(const Line &other) const {
    if (a != other.a) return a < other.a;
    return b < other.b;
  }
};

bool Bad(const Line &x, const Line &y, const Line &z) {
  return (__int128_t)(z.b - x.b) * (x.a - y.a) <= 
         (__int128_t)(y.b - x.b) * (x.a - z.a);
}

void Push(vector<Line> &v, const Line &l) {
  while ((int)v.size() >= 2 && Bad(v.end()[-2], v.end()[-1], l))
    v.pop_back();
  v.emplace_back(l);
}

int main() {
  ifstream cin("euro.in");
  ofstream cout("euro.out");

  int n, t; cin >> n >> t;
  vector<int64_t> sum(n);
  vector<int64_t> dp(n);
  for (int i = 0; i < n; ++i) {
    cin >> sum[i];
    if (i > 0) sum[i] += sum[i - 1];
    dp[i] = sum[i] * (i + 1) - t;
  }

  auto Divide = [&](int l, int r, auto self) {
    if (l == r) {
      return vector<Line>{Line(-sum[l], dp[l])};
    }

    int m = (l + r) / 2;
    auto h1 = self(l, m, self);
    for (int i = m + 1, ptr = 0; i <= r; ++i) {
      while (ptr + 1 < (int)h1.size() && h1[ptr](i + 1) <= h1[ptr + 1](i + 1)) ++ptr;
      dp[i] = max(dp[i], h1[ptr](i + 1) + sum[i] * (i + 1) - t);
    }

    auto h2 = self(m + 1, r, self);

    vector<Line> h;
    int i = 0, j = 0;
    while (i < (int)h1.size() && j < (int)h2.size()) {
      if (h1[i] < h2[j]) Push(h, h1[i++]);
      else Push(h, h2[j++]);
    }
    while (i < (int)h1.size()) Push(h, h1[i++]);
    while (j < (int)h2.size()) Push(h, h2[j++]);
    return h;
  };
  Divide(0, n - 1, Divide);

  cout << dp[n - 1] << endl;
}