Problem p03236 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define pb push_back
#define pf push_front
typedef long long lint;
typedef complex<double> P;
#define mp make_pair
#define fi first
#define se second
typedef pair<int, int> pint;
#define All(s) s.begin(), s.end()
#define rAll(s) s.rbegin(), s.rend()
#define REP(i, a, b) for (int i = a; i < b; i++)
#define rep(i, n) REP(i, 0, n)
// 問題文および制約はちゃんと確認しよう！
// サイズは10^5じゃなくて2×10^5とかかもしれないし、重要な制約・条件を見落としているかも
// とりあえずサンプルを読んでから解法を考えよう？
#define N 514
string ma[N];
int dp[N][N];           // どこまで戻れるか
int mx[N][N], mn[N][N]; // ある層への最高・最低着地点（毎回計算する）
lint num[N], sum[N];
int main() {
  lint out = 0;
  int n;
  cin >> n;
  rep(i, n) cin >> ma[i];
  rep(i, n) rep(j, n) {
    dp[i][j] = N * 2;
    if (ma[i][j] == '#')
      continue;
    dp[i][j] = i + j;
    if (i > 0)
      dp[i][j] = min(dp[i][j], dp[i - 1][j]);
    if (j > 0)
      dp[i][j] = min(dp[i][j], dp[i][j - 1]);
  }
  for (int i = n * 2 - 2; i >= 0; i--) {
    // cout<<i<<endl;
    rep(j, n + 5) rep(k, n + 5) mx[j][k] = -N, mn[j][k] = N;
    for (int j = n - 1; j >= 0; j--)
      for (int k = n - 1; k >= 0; k--) {
        if (j + k == i)
          mx[j][k] = mn[j][k] = j;
        if (j + k < i) {
          if (ma[j][k] != '#') {
            if (j < n - 1)
              mx[j][k] = max(mx[j][k], mx[j + 1][k]),
              mn[j][k] = min(mn[j][k], mn[j + 1][k]);
            if (k < n - 1)
              mx[j][k] = max(mx[j][k], mx[j][k + 1]),
              mn[j][k] = min(mn[j][k], mn[j][k + 1]);
          }
        }
        // cout<<i<<j<<k<<mx[j][k]<<mn[j][k]<<endl;
      }
    for (int j = i - 1; j >= 0; j--) {
      memset(num, 0, sizeof(num));
      memset(sum, 0, sizeof(sum));
      rep(k, n) {
        int l = i - k;
        if (l >= 0 && l < n && dp[k][l] <= j && ma[k][l] != '#')
          num[k] = (ma[k][l] - '0');
        sum[k + 1] = sum[k] + num[k];
      }
      rep(k, n) {
        int l = j - k;
        if (l >= 0 && l < n && mx[k][l] >= mn[k][l] && ma[k][l] != '#') {
          // cout<<i<<' '<<k<<' '<<l<<' '<<mx[k][l]<<' '<<mn[k][l]<<'
          // '<<(sum[mx[k][l]+1]-sum[mn[k][l]])<<endl;
          out += (ma[k][l] - '0') * (sum[mx[k][l] + 1] - sum[mn[k][l]]);
        }
      }
    }
  }
  cout << out << endl;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define pb push_back
#define pf push_front
typedef long long lint;
typedef complex<double> P;
#define mp make_pair
#define fi first
#define se second
typedef pair<int, int> pint;
#define All(s) s.begin(), s.end()
#define rAll(s) s.rbegin(), s.rend()
#define REP(i, a, b) for (int i = a; i < b; i++)
#define rep(i, n) REP(i, 0, n)
// 問題文および制約はちゃんと確認しよう！
// サイズは10^5じゃなくて2×10^5とかかもしれないし、重要な制約・条件を見落としているかも
// とりあえずサンプルを読んでから解法を考えよう？
#define N 514
string ma[N];
int dp[N][N];           // どこまで戻れるか
int mx[N][N], mn[N][N]; // ある層への最高・最低着地点（毎回計算する）
lint num[N], sum[N];
int main() {
  lint out = 0;
  int n;
  cin >> n;
  rep(i, n) cin >> ma[i];
  rep(i, n) rep(j, n) {
    dp[i][j] = N * 2;
    if (ma[i][j] == '#')
      continue;
    dp[i][j] = i + j;
    if (i > 0)
      dp[i][j] = min(dp[i][j], dp[i - 1][j]);
    if (j > 0)
      dp[i][j] = min(dp[i][j], dp[i][j - 1]);
  }
  for (int i = n * 2 - 2; i >= 0; i--) {
    // cout<<i<<endl;
    rep(j, n + 5) rep(k, min(n, i - j) + 5) mx[j][k] = -N, mn[j][k] = N;
    for (int j = n - 1; j >= 0; j--)
      for (int k = n - 1; k >= 0; k--) {
        if (j + k == i)
          mx[j][k] = mn[j][k] = j;
        if (j + k < i) {
          if (ma[j][k] != '#') {
            if (j < n - 1)
              mx[j][k] = max(mx[j][k], mx[j + 1][k]),
              mn[j][k] = min(mn[j][k], mn[j + 1][k]);
            if (k < n - 1)
              mx[j][k] = max(mx[j][k], mx[j][k + 1]),
              mn[j][k] = min(mn[j][k], mn[j][k + 1]);
          }
        }
        // cout<<i<<j<<k<<mx[j][k]<<mn[j][k]<<endl;
      }
    for (int j = i - 1; j >= 0; j--) {
      memset(num, 0, sizeof(num));
      memset(sum, 0, sizeof(sum));
      rep(k, n) {
        int l = i - k;
        if (l >= 0 && l < n && dp[k][l] <= j && ma[k][l] != '#')
          num[k] = (ma[k][l] - '0');
        sum[k + 1] = sum[k] + num[k];
      }
      rep(k, n) {
        int l = j - k;
        if (l >= 0 && l < n && mx[k][l] >= mn[k][l] && ma[k][l] != '#') {
          // cout<<i<<' '<<k<<' '<<l<<' '<<mx[k][l]<<' '<<mn[k][l]<<'
          // '<<(sum[mx[k][l]+1]-sum[mn[k][l]])<<endl;
          out += (ma[k][l] - '0') * (sum[mx[k][l] + 1] - sum[mn[k][l]]);
        }
      }
    }
  }
  cout << out << endl;
}