class Solution {
 public:
  bool possibleToStamp(vector<vector<int>>& grid, int stampHeight,
                       int stampWidth) {
    const int m = grid.size();
    const int n = grid[0].size();
    // A[i][j] := the number of 1s in grid[0..i)[0..j)
    vector<vector<int>> A(m + 1, vector<int>(n + 1));
    // B[i][j] := the number of ways to stamp the submatrix in [0..i)[0..j)
    vector<vector<int>> B(m + 1, vector<int>(n + 1));
    // fit[i][j] := true if the stamps can fit with the right-bottom at (i, j)
    vector<vector<bool>> fit(m, vector<bool>(n));
    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j) {
        A[i + 1][j + 1] = A[i + 1][j] + A[i][j + 1] - A[i][j] + grid[i][j];
        if (i + 1 >= stampHeight && j + 1 >= stampWidth) {
          const int x = i - stampHeight + 1;
          const int y = j - stampWidth + 1;
          if (A[i + 1][j + 1] - A[x][j + 1] - A[i + 1][y] + A[x][y] == 0)
            fit[i][j] = true;
        }
      }
    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        B[i + 1][j + 1] = B[i + 1][j] + B[i][j + 1] - B[i][j] + fit[i][j];
    for (int i = 0; i < m; ++i)
      for (int j = 0; j < n; ++j)
        if (!grid[i][j]) {
          const int x = min(i + stampHeight, m);
          const int y = min(j + stampWidth, n);
          if (B[x][y] - B[i][y] - B[x][j] + B[i][j] == 0)
            return false;
        }
    return true;
  }
};