Problem p01429 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = (1LL << 50);
int N, M, L;
int t[2000];
ll u[100005];
ll dp[2001][2001];

ll calc(int a, int b) {
  if (a > b)
    swap(a, b);
  return (u[b] - u[a - 1]) / (ll)L;
}

int main() {
  scanf("%d %d %d", &N, &M, &L);
  for (int i = 0; i < N; i++)
    scanf("%d", &t[i]);
  sort(t, t + N);

  for (int i = 1; i <= M; i++) {
    scanf("%lld", &u[i]);
    u[i] += u[i - 1];
  }
  ll ans = INF;
  fill(dp[0], dp[2001], INF);
  dp[0][0] = 0;
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      if (dp[i][j] == INF)
        continue;
      int k = max(i, j) + 1;
      if (k < N) {
        dp[k][j] = min(dp[k][j], dp[i][j] + calc(t[i], t[k]));
        dp[i][k] = min(dp[k][i], dp[i][j] + calc(t[j], t[k]));
      } else {
        ans = min(ans, dp[i][j] + calc(t[N - 1], t[min(i, j)]));
      }
    }
  }

  cout << ans << endl;
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define MAX_V 4005
typedef pair<ll, int> P;
ll INF = 1000000000000000000LL;

struct edge {
  ll to, cap, cost, rev;
};

int V;
vector<edge> G[MAX_V];
ll dist[MAX_V], h[MAX_V];
int prevv[MAX_V], preve[MAX_V];

void init_edge() {
  for (int i = 0; i < V; i++)
    G[i].clear();
}

void add_edge(ll from, ll to, ll cap, ll cost) {
  G[from].push_back((edge){to, cap, cost, (int)G[to].size()});
  G[to].push_back((edge){from, 0, -cost, (int)G[from].size() - 1});
}

ll min_cost_flow(int s, int t, int f) {
  ll res = 0;
  fill(h, h + V, 0);
  fill(dist, dist + V, INF);
  dist[s] = 0;
  bool update = true;
  while (update) {
    update = false;
    for (int v = 0; v < V; v++) {
      if (dist[v] == INF)
        continue;
      for (int i = 0; i < (int)G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
          dist[e.to] = dist[v] + e.cost;
          prevv[e.to] = v;
          preve[e.to] = i;
          update = true;
        }
      }
    }
  }
  if (dist[t] == INF)
    return -1;
  for (int v = 0; v < V; v++)
    h[v] += dist[v];

  ll d = f;
  for (int v = t; v != s; v = prevv[v]) {
    d = min(d, G[prevv[v]][preve[v]].cap);
  }
  f -= d;
  res += d * dist[t];
  for (int v = t; v != s; v = prevv[v]) {
    edge &e = G[prevv[v]][preve[v]];
    e.cap -= d;
    G[v][e.rev].cap += d;
  }

  while (f > 0) {

    priority_queue<P, vector<P>, greater<P>> que;
    fill(dist, dist + V, INF);
    dist[s] = 0;
    que.push(P(0, s));
    while (!que.empty()) {
      P p = que.top();
      que.pop();
      int v = p.second;
      if (dist[v] < p.first)
        continue;
      for (int i = 0; i < (int)G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
          dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
          prevv[e.to] = v;
          preve[e.to] = i;
          que.push(P(dist[e.to], e.to));
        }
      }
    }

    if (dist[t] == INF) {
      return -1;
    }
    for (int v = 0; v < V; v++)
      h[v] += dist[v];

    ll d = f;
    for (int v = t; v != s; v = prevv[v]) {
      d = min(d, G[prevv[v]][preve[v]].cap);
    }
    f -= d;
    res += d * h[t];
    for (int v = t; v != s; v = prevv[v]) {
      edge &e = G[prevv[v]][preve[v]];
      e.cap -= d;
      G[v][e.rev].cap += d;
    }
  }

  return res;
}

int N, M, L;
int t[2000];
ll u[100005];

ll calc(int a, int b) {
  if (a > b)
    swap(a, b);
  return (u[b] - u[a - 1]) / (ll)L;
}

int main() {
  scanf("%d %d %d", &N, &M, &L);
  for (int i = 0; i < N; i++)
    scanf("%d", &t[i]);
  sort(t, t + N);

  for (int i = 1; i <= M; i++) {
    scanf("%lld", &u[i]);
    u[i] += u[i - 1];
  }

  ll D = 10000000000LL;
  for (int i = 1; i < N - 1; i++)
    add_edge(i, N + i, 1, -D);

  for (int i = 0; i < N; i++) {
    for (int j = i + 1; j < N; j++) {
      ll key = calc(t[i], t[j]);
      add_edge(N + i, j, 1, key);
    }
  }
  V = N + N;
  cout << min_cost_flow(N, N - 1, 2) + D * (N - 2) << endl;
  return 0;
}