Problem p03237 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define ri register int
const int N = 505;
int a[N][N], f[N][N], l[N][N], r[N][N];
char s[N];
/*
f[i][j] (i,j) 能走到的位置的权值和
l[i][j][k]/r[i][j][k] 表示 (i,j) 可以到达的第 k 行最左/右的位置 ，第一维省略
不能走到的点贡献相当于已经清零，因为 (i+1,j) (i,j+1)
共同能走到的点的递增序列里面不会出现这些位置，
且没有被计算到其左上的点的贡献中去
*/
int main() {
  //	freopen("cell.in","r",stdin);
  //	freopen("cell.out","w",stdout);
  ri n, i, j, k, now;
  register long long ans;
  scanf("%d", &n);
  for (i = 1; i <= n; ++i) {
    scanf("%s", s + 1);
    for (j = 1; j <= n; ++j)
      a[i][j] = s[j] == '#' ? 0 : s[j] - '0';
  }
  ans = 0;
  for (i = n; i; --i)
    for (j = n; j; --j) {
      if (a[i][j] == 0) {
        memset(l[j] + i, 127, sizeof(int) * (n - i + 1));
        memset(r[j] + i, 128, sizeof(int) * (n - i + 1));
        continue;
      }
      if (a[i + 1][j] == 0 && a[i][j + 1] == 0)
        l[j][i] = r[j][i] = j;
      else if (a[i + 1][j] == 0)
        memcpy(l[j] + i, l[j + 1] + i, sizeof(int) * (n - i + 1)),
            memcpy(r[j] + i, r[j + 1] + i, sizeof(int) * (n - i + 1)),
            l[j][i] = j, f[i][j] = f[i][j + 1];
      else if (a[i][j + 1] == 0)
        l[j][i] = r[j][i] = j, f[i][j] = f[i + 1][j];
      else {
        f[i][j] = f[i][j + 1] + f[i + 1][j];
        l[j][i] = j;
        r[j][i] = r[j + 1][i];
        now = 0;
        for (k = i + 1; k <= n; ++k) {
          if (r[j][k] >= l[j + 1][k] && l[j + 1][k] > now)
            //	printf("sub %d %d %d %d\n",i,j,k,l[j+1][k]),
            f[i][j] -= f[k][l[j + 1][k]];
          now = max(now, r[j][k]);
          l[j][k] = min(l[j][k], l[j + 1][k]);
          r[j][k] = max(r[j][k], r[j + 1][k]);
        }
      }
      ans += a[i][j] * f[i][j];
      //	printf("f %d %d %d\n",i,j,f[i][j]);
      f[i][j] += a[i][j];
      //	printf("check (%d,%d)\n",i,j);
      //	for(k=i;k<=n;++k)
      //		printf("%d %d %d\n",k,l[j][k],r[j][k]);
    }
  printf("%lld\n", ans);
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define ri register int
const int N = 1505;
int a[N][N], f[N][N], l[N][N], r[N][N];
char s[N];
/*
f[i][j] (i,j) 能走到的位置的权值和
l[i][j][k]/r[i][j][k] 表示 (i,j) 可以到达的第 k 行最左/右的位置 ，第一维省略
不能走到的点贡献相当于已经清零，因为 (i+1,j) (i,j+1)
共同能走到的点的递增序列里面不会出现这些位置，
且没有被计算到其左上的点的贡献中去
*/
int main() {
  //	freopen("cell.in","r",stdin);
  //	freopen("cell.out","w",stdout);
  ri n, i, j, k, now;
  register long long ans;
  scanf("%d", &n);
  for (i = 1; i <= n; ++i) {
    scanf("%s", s + 1);
    for (j = 1; j <= n; ++j)
      a[i][j] = s[j] == '#' ? 0 : s[j] - '0';
  }
  ans = 0;
  for (i = n; i; --i)
    for (j = n; j; --j) {
      if (a[i][j] == 0) {
        memset(l[j] + i, 127, sizeof(int) * (n - i + 1));
        memset(r[j] + i, 128, sizeof(int) * (n - i + 1));
        continue;
      }
      if (a[i + 1][j] == 0 && a[i][j + 1] == 0)
        l[j][i] = r[j][i] = j;
      else if (a[i + 1][j] == 0)
        memcpy(l[j] + i, l[j + 1] + i, sizeof(int) * (n - i + 1)),
            memcpy(r[j] + i, r[j + 1] + i, sizeof(int) * (n - i + 1)),
            l[j][i] = j, f[i][j] = f[i][j + 1];
      else if (a[i][j + 1] == 0)
        l[j][i] = r[j][i] = j, f[i][j] = f[i + 1][j];
      else {
        f[i][j] = f[i][j + 1] + f[i + 1][j];
        l[j][i] = j;
        r[j][i] = r[j + 1][i];
        now = 0;
        for (k = i + 1; k <= n; ++k) {
          if (r[j][k] >= l[j + 1][k] && l[j + 1][k] > now)
            //	printf("sub %d %d %d %d\n",i,j,k,l[j+1][k]),
            f[i][j] -= f[k][l[j + 1][k]];
          now = max(now, r[j][k]);
          l[j][k] = min(l[j][k], l[j + 1][k]);
          r[j][k] = max(r[j][k], r[j + 1][k]);
        }
      }
      ans += a[i][j] * f[i][j];
      //	printf("f %d %d %d\n",i,j,f[i][j]);
      f[i][j] += a[i][j];
      //	printf("check (%d,%d)\n",i,j);
      //	for(k=i;k<=n;++k)
      //		printf("%d %d %d\n",k,l[j][k],r[j][k]);
    }
  printf("%lld\n", ans);
  return 0;
}