Filled Subgrid Count I
Problem Overview
| Attribute | Value |
|---|---|
| Difficulty | Medium |
| Category | Grid / Counting |
| Time Limit | 1 second |
| Key Technique | 2D Prefix Sums / Early Termination |
| CSES Link | Filled Subgrid Count I |
Learning Goals
After solving this problem, you will be able to:
- Understand how to enumerate all k x k subgrids in a 2D grid
- Apply early termination optimization for uniformity checking
- Use 2D prefix sums to accelerate subgrid queries
- Recognize when brute force with pruning is acceptable
Problem Statement
Problem: Given an n x m grid of integers, count the number of k x k subgrids where all cells contain the same value (filled subgrids).
Input:
- Line 1: Three integers n, m, k (grid dimensions and subgrid size)
- Next n lines: m integers each (grid values)
Output:
- One integer: the count of filled k x k subgrids
Constraints:
- 1 <= n, m <= 100
- 1 <= k <= min(n, m)
- 1 <= grid[i][j] <= 10^9
Example
Input:
3 4 2
1 1 2 2
1 1 2 2
3 3 3 3
Output:
4
Explanation: The four filled 2x2 subgrids are:
- (0,0): all 1s
- (0,2): all 2s
- (1,0): values [1,1,3,3] - NOT filled
- (1,2): all 2s and 3s mixed - NOT filled
- Actually: positions (0,0), (0,2), (1,2) have uniform values, plus bottom-right corner.
Intuition: How to Think About This Problem
Pattern Recognition
Key Question: How can we efficiently check if all cells in a subgrid have the same value?
The naive approach checks all k^2 cells for each subgrid. The insight is that we can:
- Early terminate when we find a mismatched value
- Use prefix sums to check if sum equals k^2 times the first element
Breaking Down the Problem
- What are we looking for? Count of k x k subgrids with uniform values
- What information do we have? Grid dimensions, subgrid size, cell values
- What’s the relationship? A subgrid is “filled” iff all k^2 cells equal the top-left cell
Analogies
Think of this like checking if a patch of tiles on a floor all have the same color. You can either check each tile one-by-one (stopping early if you find a different color), or use a clever counting method.
Solution 1: Brute Force with Early Termination
Idea
For each possible k x k subgrid position, check if all cells match the top-left value. Stop immediately when a mismatch is found.
Algorithm
- Iterate through all valid top-left corners: (i, j) where i <= n-k and j <= m-k
- For each position, get the reference value at (i, j)
- Check all k^2 cells; return false immediately on mismatch
- Count subgrids that pass the check
Code
Python:
import sys
input = sys.stdin.readline
def solve():
n, m, k = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
count = 0
for i in range(n - k + 1):
for j in range(m - k + 1):
if is_filled(grid, i, j, k):
count += 1
print(count)
def is_filled(grid, r, c, k):
"""Check if k x k subgrid starting at (r,c) is uniform."""
val = grid[r][c]
for i in range(r, r + k):
for j in range(c, c + k):
if grid[i][j] != val:
return False
return True
solve()
Complexity
| Metric | Value | Explanation |
|---|---|---|
| Time | O((n-k+1) * (m-k+1) * k^2) | Check each subgrid, each cell |
| Space | O(1) | No extra space beyond input |
Why This Works (But Can Be Slow)
Early termination helps in practice - mixed subgrids are rejected quickly. However, worst case (all uniform grid) still checks all cells.
Solution 2: Optimal with 2D Prefix Sums
Key Insight
The Trick: If all k^2 cells have value v, then sum of subgrid = k^2 * v. Use 2D prefix sums for O(1) subgrid sum queries.
Why Prefix Sums Help
Instead of checking k^2 cells, we:
- Compute the subgrid sum in O(1) using prefix sums
- Compare:
sum == k * k * grid[r][c]
Caveat: This only works when values are non-negative and the equality is mathematically sound. For large values, we must be careful about overflow.
2D Prefix Sum Formula
For prefix sum array P:
P[i][j] = sum of grid[0..i-1][0..j-1]
Sum of subgrid (r1,c1) to (r2,c2):
= P[r2+1][c2+1] - P[r1][c2+1] - P[r2+1][c1] + P[r1][c1]
Dry Run Example
Let’s trace with:
Grid (3x3, k=2):
1 1 2
1 1 2
3 3 3
Prefix Sum Array P (4x4, 1-indexed for convenience):
0 0 0 0
0 1 2 4
0 2 4 8
0 5 10 18
Check subgrid at (0,0):
Reference value = grid[0][0] = 1
Expected sum = 2 * 2 * 1 = 4
Actual sum = P[2][2] - P[0][2] - P[2][0] + P[0][0]
= 4 - 0 - 0 + 0 = 4
4 == 4? YES -> filled!
Check subgrid at (0,1):
Reference value = grid[0][1] = 1
Expected sum = 4 * 1 = 4
Actual sum = P[2][3] - P[0][3] - P[2][1] + P[0][1]
= 8 - 0 - 2 + 0 = 6
6 == 4? NO -> not filled
Check subgrid at (1,0):
Reference value = grid[1][0] = 1
Expected sum = 4 * 1 = 4
Actual sum = P[3][2] - P[1][2] - P[3][0] + P[1][0]
= 10 - 2 - 0 + 0 = 8
8 == 4? NO -> not filled
Check subgrid at (1,1):
Reference value = grid[1][1] = 1
Expected sum = 4
Actual sum = P[3][3] - P[1][3] - P[3][1] + P[1][1]
= 18 - 4 - 5 + 1 = 10
10 == 4? NO -> not filled
Result: 1 filled subgrid
Code
Python:
import sys
input = sys.stdin.readline
def solve():
n, m, k = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# Build 2D prefix sum
prefix = [[0] * (m + 1) for _ in range(n + 1)]
for i in range(n):
for j in range(m):
prefix[i+1][j+1] = (grid[i][j] + prefix[i][j+1]
+ prefix[i+1][j] - prefix[i][j])
def subgrid_sum(r1, c1, r2, c2):
"""Sum of subgrid from (r1,c1) to (r2,c2) inclusive."""
return (prefix[r2+1][c2+1] - prefix[r1][c2+1]
- prefix[r2+1][c1] + prefix[r1][c1])
count = 0
target_cells = k * k
for i in range(n - k + 1):
for j in range(m - k + 1):
val = grid[i][j]
actual_sum = subgrid_sum(i, j, i + k - 1, j + k - 1)
if actual_sum == target_cells * val:
# Verify with early-termination check (handles collision cases)
if is_truly_filled(grid, i, j, k):
count += 1
print(count)
def is_truly_filled(grid, r, c, k):
"""Double-check uniformity (handles hash collision-like cases)."""
val = grid[r][c]
for i in range(r, r + k):
for j in range(c, c + k):
if grid[i][j] != val:
return False
return True
solve()
Complexity
| Metric | Value | Explanation |
|---|---|---|
| Time | O(n * m) average | Prefix sum filters most candidates |
| Space | O(n * m) | Prefix sum array |
Common Mistakes
Mistake 1: Off-by-One in Subgrid Boundaries
# WRONG - goes out of bounds
for i in range(n - k): # Should be n - k + 1
for j in range(m - k):
...
Problem: Misses the last valid row/column of subgrids.
Fix: Use range(n - k + 1) to include all valid positions.
Mistake 2: Integer Overflow in Sum Calculation
Problem: With k=100 and value=10^9, product exceeds 32-bit range.
Fix: Use long long for sum calculations.
Mistake 3: Trusting Prefix Sum Alone
# WRONG - assumes sum equality means uniformity
if subgrid_sum == k * k * grid[r][c]:
count += 1 # False positive possible!
Problem: Different values can sum to same total (e.g., [1,3] vs [2,2]). Fix: Either verify with direct check, or use additional constraints.
Edge Cases
| Case | Input | Expected Output | Why |
|---|---|---|---|
| k equals grid size | n=2, m=2, k=2, uniform grid | 1 | Only one possible subgrid |
| k = 1 | Any grid, k=1 | n * m | Every cell is a trivial filled subgrid |
| All different values | No two cells match | 0 (if k>1) | No uniform subgrids exist |
| All same value | Entire grid is uniform | (n-k+1) * (m-k+1) | Every subgrid is filled |
| Single row/column | n=1 or m=1 | Depends on k | Linear subgrid counting |
When to Use This Pattern
Use This Approach When:
- Counting uniform/homogeneous subregions in 2D grids
- Subgrid size k is fixed and given
- Need to verify a property across all cells of a subregion
Don’t Use When:
- Looking for the largest uniform subgrid (use DP instead)
- Subgrid sizes vary (different approach needed)
- Grid is sparse (consider coordinate compression)
Pattern Recognition Checklist:
- Fixed-size subgrid queries? -> Consider 2D prefix sums
- Checking uniformity? -> Early termination helps
- Counting subregions? -> Enumerate all top-left corners
Related Problems
Easier (Do These First)
| Problem | Why It Helps |
|---|---|
| Static Range Sum Queries | 1D prefix sums foundation |
| Forest Queries | 2D prefix sums basics |
Similar Difficulty
| Problem | Key Difference |
|---|---|
| Maximal Square (LeetCode) | Find largest uniform square |
| Count Square Submatrices (LeetCode) | Count all sizes, DP approach |
Harder (Do These After)
| Problem | New Concept |
|---|---|
| Filled Subgrid Count II | Larger constraints, optimization needed |
| Maximal Rectangle (LeetCode) | Histogram-based approach |
Key Takeaways
- The Core Idea: Enumerate all k x k positions and verify uniformity efficiently
- Time Optimization: Early termination on first mismatch; prefix sums for O(1) range queries
- Space Trade-off: O(n*m) prefix array enables faster filtering
- Pattern: Fixed-size 2D subgrid counting with uniformity constraint
Practice Checklist
Before moving on, make sure you can:
- Build a 2D prefix sum array correctly
- Query any rectangular subgrid sum in O(1)
- Handle off-by-one errors in grid boundary iteration
- Implement early termination for uniformity checking
- Analyze when prefix sums provide benefit vs. overhead
Additional Resources
- CP-Algorithms: 2D Prefix Sums
- CSES Forest Queries - 2D prefix sum application
- LeetCode Grid Problems