Problem p03173 (C++)

Buggy submission (status: Runtime Error):
/************
 * 	@Just Another Source code by: ankit.sangwan1999
 *	@created on: 24 Jun 2020
 *	@Based On : MCM
 */
#include <bits/stdc++.h>
using namespace std;
#define fastio                                                                 \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL) //;cout.tie(NULL)
#define ll long long
const int mod = 1e9 + 7;
const long double pie = 3.14159265358979323846;
#define endl '\n'
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
gp_hash_table<int, ll> ma; // orderd_map using pb_ds
const int N = 405;
ll dp[N][N];
ll sum[N];

void pre_sum(int *arr, int n) {
  sum[0] = arr[0];
  for (int i = 1; i < n; i++)
    sum[i] = sum[i - 1] + arr[i];
}

// Cost of interval l to r is -> minimum among the partitions from (k=i to k=j)
// + sum of terms i to j dp[i][j] -> stores the minimum cost of the interval i
// to j.

// O(n^3) time and space
ll MCM(int i, int j, int *arr) {
  if (dp[i][j] != -1)
    return dp[i][j];

  if (i == j) {
    return dp[i][j] = 0;
  }

  ll ans = ULLONG_MAX / 2;

  ll curr_cost =
      (i == 0 ? sum[j]
              : sum[j] - sum[i - 1]); // sum till i to j.(cost of joining the
                                      // left and right intervals)

  for (int k = i; k < j; k++) {

    ll left_cost = MCM(i, k, arr);
    ll right_cost = MCM(k + 1, j, arr);
    ll tmp = left_cost + right_cost + curr_cost;
    ans = min(ans, tmp);
  }
  return dp[i][j] = ans;
}

void solve() {
  memset(dp, -1, sizeof(dp));
  int n;
  cin >> n;
  int arr[n];
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
  }
  pre_sum(arr, n); // to calculate the prefix sums.
  // TOP DOWN
  // cout<<MCM(0,n-1, arr);

  // Bottom-Up:
  for (int len = 1; len <= n; len++) { // length of interval -> moving from
                                       // smaller to larger intervals.
    for (int i = 0; i < n; i++) {      // fixing the starting point.
      int j = i + len - 1;
      // considering interval i to j
      if (i == j) {
        dp[i][j] = 0;
      } else {
        ll tmp = ULLONG_MAX / 2;
        ll curr_cost =
            (i == 0 ? sum[j]
                    : sum[j] - sum[i - 1]); // sum till i to j.(cost of joining
                                            // the left and right intervals)
        for (int k = i; k < j; k++) {
          tmp = min(tmp, dp[i][k] + dp[k + 1][j] + curr_cost);
        }
        dp[i][j] = tmp;
      }
    }
  }

  cout << dp[0][n - 1] << endl;
}
signed main() {

  fastio;
  int t = 1;
  // cin>>t;

  while (--t >= 0) {
    solve();
  }

  return 0;
}

Fixed submission:
/************
 * 	@Just Another Source code by: ankit.sangwan1999
 *	@created on: 24 Jun 2020
 *	@Based On : MCM
 */
#include <bits/stdc++.h>
using namespace std;
#define fastio                                                                 \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(NULL) //;cout.tie(NULL)
#define ll long long
const int mod = 1e9 + 7;
const long double pie = 3.14159265358979323846;
#define endl '\n'
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
gp_hash_table<int, ll> ma; // orderd_map using pb_ds
const int N = 405;
ll dp[N][N];
ll sum[N];

void pre_sum(int *arr, int n) {
  sum[0] = arr[0];
  for (int i = 1; i < n; i++)
    sum[i] = sum[i - 1] + arr[i];
}

// Cost of interval l to r is -> minimum among the partitions from (k=i to k=j)
// + sum of terms i to j dp[i][j] -> stores the minimum cost of the interval i
// to j.

// O(n^3) time and space
ll MCM(int i, int j, int *arr) {
  if (dp[i][j] != -1)
    return dp[i][j];

  if (i == j) {
    return dp[i][j] = 0;
  }

  ll ans = ULLONG_MAX / 2;

  ll curr_cost =
      (i == 0 ? sum[j]
              : sum[j] - sum[i - 1]); // sum till i to j.(cost of joining the
                                      // left and right intervals)

  for (int k = i; k < j; k++) {

    ll left_cost = MCM(i, k, arr);
    ll right_cost = MCM(k + 1, j, arr);
    ll tmp = left_cost + right_cost + curr_cost;
    ans = min(ans, tmp);
  }
  return dp[i][j] = ans;
}

void solve() {
  memset(dp, -1, sizeof(dp));
  int n;
  cin >> n;
  int arr[n];
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
  }
  pre_sum(arr, n); // to calculate the prefix sums.
  // TOP DOWN
  // cout<<MCM(0,n-1, arr);

  // Bottom-Up:
  for (int len = 1; len <= n; len++) {   // length of interval -> moving from
                                         // smaller to larger intervals.
    for (int i = 0; i <= n - len; i++) { // fixing the starting point.
      int j = i + len - 1;
      // considering interval i to j
      if (i == j) {
        dp[i][j] = 0;
      } else {
        ll tmp = ULLONG_MAX / 2;
        ll curr_cost =
            (i == 0 ? sum[j]
                    : sum[j] - sum[i - 1]); // sum till i to j.(cost of joining
                                            // the left and right intervals)
        for (int k = i; k < j; k++) {
          tmp = min(tmp, dp[i][k] + dp[k + 1][j] + curr_cost);
        }
        dp[i][j] = tmp;
      }
    }
  }

  cout << dp[0][n - 1] << endl;
}
signed main() {

  fastio;
  int t = 1;
  // cin>>t;

  while (--t >= 0) {
    solve();
  }

  return 0;
}