class Solution {
  private int[] getSuffixSum(int[] piles) {
    var suffix = new int[piles.length + 1];

    for (int i = piles.length - 1; i >= 0; --i) {
      suffix[i] = suffix[i + 1] + piles[i];
    }

    return suffix;
  }

  private void compute(int n, int[] suffix, int[][] dp, int i) {
    var row = dp[i];

    for (int maxAllowed = n - 1; maxAllowed >= 1; --maxAllowed) {
      for (int x = 1; x <= 2 * maxAllowed && i + x <= n; ++x) {
        row[maxAllowed] = Math.max(row[maxAllowed], suffix[i] - dp[i + x][Math.max(maxAllowed, x)]);
      }
    }
  }

  public int stoneGameII(int[] piles) {
    int n = piles.length;

    var suffix = getSuffixSum(piles);

    var dp = new int[n + 1][n + 1];
    // Handle base case.
    for (int i = 0; i <= n; ++i) {
      dp[i][n] = suffix[i];
    }

    for (int i = n - 1; i >= 0; --i) {
      compute(n, suffix, dp, i);
    }

    return dp[0][1];
  }
}