Problem p00548 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <iostream>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; ++i)
#define rep(i, n) REP(i, 0, n)

using namespace std;

typedef long long ll;

#define MAX 20010

ll dp[MAX];
int N, M;
ll K, A[MAX];

void computer() {
  rep(i, N + 1) dp[i] = LLONG_MAX;
  rep(i, N) {
    dp[i] = ((i - 1 >= 0) ? dp[i - 1] : 0) + K;
    ll maxi = A[i];
    ll mini = A[i];
    for (int j = i - 1; j >= 0; --j) {
      if (i - j + 1 > M)
        break;
      maxi = max(maxi, A[j]);
      mini = min(mini, A[j]);
      dp[i] = min(dp[i], ((j - 1 >= 0) ? dp[j - 1] : 0) + K +
                             (ll)(i - j + 1) * (maxi - mini));
    }
  }
  cout << dp[N - 1] << endl;
}

int main() {
  cin >> N >> M >> K;
  rep(i, N) cin >> A[i];
  computer();
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstring>
#include <iostream>
#include <vector>

#define REP(i, s, n) for (int i = s; i < n; ++i)
#define rep(i, n) REP(i, 0, n)

using namespace std;

typedef long long ll;
const int IINF = INT_MAX;

class RMQ {
private:
  int limit, N;
  vector<int> dat;

public:
  void init(int n_) {
    N = n_;
    limit = 1;
    while (limit < n_)
      limit *= 2;
    dat.clear();
    dat.resize(2 * limit, -IINF);
  }

  int _build(int cur, int L, int R, const vector<int> &buf) {
    if (!(0 <= cur && cur < 2 * limit))
      return -IINF;
    if (L == R - 1) {
      if (L >= N)
        return -IINF;
      dat[cur] = buf[L];
    } else {
      int vl = _build(cur * 2 + 1, L, (L + R) / 2, buf);
      int vr = _build(cur * 2 + 2, (L + R) / 2, R, buf);
      dat[cur] = max(vl, vr);
    }
    return dat[cur];
  }

  void build(const vector<int> &buf) { _build(0, 0, limit, buf); };

  void update(int k, int a) {
    k += limit - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  int _query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return -IINF;
    else if (a <= l && r <= b)
      return dat[k];
    int vl = _query(a, b, k * 2 + 1, l, (l + r) / 2);
    int vr = _query(a, b, k * 2 + 2, (l + r) / 2, r);
    return max(vl, vr);
  }

  int query(int a, int b) { return _query(a, b, 0, 0, limit); }
};

class RRMQ {
private:
  int limit, N;
  vector<int> dat;

public:
  void init(int n_) {
    N = n_;
    limit = 1;
    while (limit < n_)
      limit *= 2;
    dat.clear();
    dat.resize(2 * limit, IINF);
  }

  int _build(int cur, int L, int R, const vector<int> &buf) {
    if (!(0 <= cur && cur < 2 * limit))
      return IINF;
    if (L == R - 1) {
      if (L >= N)
        return IINF;
      dat[cur] = buf[L];
    } else {
      int vl = _build(cur * 2 + 1, L, (L + R) / 2, buf);
      int vr = _build(cur * 2 + 2, (L + R) / 2, R, buf);
      dat[cur] = min(vl, vr);
    }
    return dat[cur];
  }

  void build(const vector<int> &buf) { _build(0, 0, limit, buf); };

  void update(int k, int a) {
    k += limit - 1;
    dat[k] = a;
    while (k > 0) {
      k = (k - 1) / 2;
      dat[k] = min(dat[k * 2 + 1], dat[k * 2 + 2]);
    }
  }

  int _query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l)
      return IINF;
    else if (a <= l && r <= b)
      return dat[k];
    int vl = _query(a, b, k * 2 + 1, l, (l + r) / 2);
    int vr = _query(a, b, k * 2 + 2, (l + r) / 2, r);
    return min(vl, vr);
  }

  int query(int a, int b) { return _query(a, b, 0, 0, limit); }
};

#define MAX 20010

ll dp[MAX];
int N, M;
ll K, A[MAX];

void computer() {
  RMQ maxt;
  RRMQ mint;
  {
    maxt.init(N);
    mint.init(N);
    vector<int> vec(N);
    rep(i, N) vec[i] = A[i];
    maxt.build(vec);
    mint.build(vec);
  }
  rep(i, N + 1) dp[i] = LLONG_MAX;
  rep(i, N) {
    dp[i] = ((i - 1 >= 0) ? dp[i - 1] : 0) + K;
    for (int j = i - 1; j >= 0; --j) {
      if (i - j + 1 > M)
        break;
      if (j - 1 >= 0 && dp[j - 1] + K >= dp[i])
        continue;
      ll maxi = maxt.query(j, i + 1);
      ll mini = mint.query(j, i + 1);
      dp[i] = min(dp[i], ((j - 1 >= 0) ? dp[j - 1] : 0) + K +
                             (ll)(i - j + 1) * (maxi - mini));
    }
  }
  cout << dp[N - 1] << endl;
}

int main() {
  cin >> N >> M >> K;
  rep(i, N) cin >> A[i];
  computer();
  return 0;
}