Please subscribe to the official Codeforces channel in Telegram via the link https://t.me/codeforces_official. ×

one_autum_leaf's blog

By one_autum_leaf, history, 9 months ago, In English

Question:

You have a $$$N * M$$$ matrix. The color of cell in $$$i^{th}$$$ row and $$$j^{th}$$$ column is $$$a_{ij}$$$. Find the number of submatrices (rectangles that can be formed by considering a range of continuous rows and columns), that have all cells of same color.

Idea:

Let $$$i_l, j_l$$$ be the coordinates of the top left corner and $$$i_r, j_r$$$ be the coordinates of the bottom right corner. We can see that $$$(i_l, j_l, i_r, j_r)$$$ uniquely define a rectangle.

Let's call a rectangle valid if it has all cells of same color.

Now let $$$dp[i][j]$$$ be the number of valid rectangles with their bottom right corner at $$$(i, j)$$$.

Let $$$h[i][j]$$$ be the "height" of columns at $$$(i, j)$$$. That is

$$$h[i][j]$$$ = max value of $$$len$$$ such that $$$a[i][j] = a[i][t]$$$ , for all $$$t = i - len + 1, i - len + 2, ..., i$$$.

How do we computer $$$dp[i][j]$$$ efficiently ?

Consider how $$$dp[i][j]$$$ depends on $$$dp[i-1][j], dp[i - 2][j], ...$$$.

For some $$$k, k < j$$$, if $$$a[i][k] != a[i][j]$$$, then $$$dp[i][k]$$$ will make no contribution to $$$dp[i][j]$$$. So let's assume that $$$a[i][t] = a[i][j]$$$ for all $$$t = k, k + 1, ..., j$$$.

Now what is the maximum height of rectangle with bottom right corner at $$$(i, j)$$$ and top left corner in the column $$$k$$$ ?

It is $$$height_k = min_{k \le t \le i}(h[i][t])$$$. Then then the number of such rectangles is $$$height_k$$$, since we can have rectangles of height $$$1, 2, 3, ..., height_k$$$.

Also consider that if $$$h[i][k] \le height_k$$$, then for any rectangle with bottom right corner at $$$(i, k)$$$ can be extended so that it has bottom right corner at $$$(i, j)$$$.

Let $$$k$$$ be the first index such that $$$a[i][k] = a[i][j]$$$ and $$$h[i][k] < h[i][j]$$$.

Then every rectangle with bottom right corner at $$$(i, k)$$$ can be extended to $$$(i, j)$$$. Also the height of any rectangle with top-left corner after $$$(i, k)$$$ is at most $$$h[i][j]$$$, since by definition for any $$$t, k < t \le i$$$ we have $$$h[i][t] \ge h[i][j]$$$.

Thus the number of rectangles after k are $$$h[i][j] * (j - k)$$$.

Thus we have, $$$dp[i][j] = dp[i][k] + h[i][j] * (j - k)$$$.

Now the question is how do we efficiently find $$$k$$$ ?

We can do this by maintaining an array of indices $$$col$$$ such that $$$h[i][col] \lt min_{col \le t \le j}(h[i][t])$$$.

Time Complexity : $$$O(N * M)$$$


vector<vector<ll>> get_number_of_rectangles(vector<vector<int>> &a, int n, int m){ vector<vector<ll>> dp(n, vector<ll>(m)); vector<vector<ll>> h(n, vector<ll>(m, 1)); for(int i = 1; i < n; ++i){ for(int j = 0; j < m; ++j){ if(a[i - 1][j] == a[i][j]){ h[i][j] += h[i - 1][j]; } } } for(int i = 0; i < n; ++i){ vector<int> indices; for(int j = 0; j < m; ++j){ int k = -1; while(!indices.empty()){ int col = indices.back(); if((a[i][col] != a[i][j]) || (h[i][col] < h[i][j])){ break; } indices.pop_back(); } if(!indices.empty()){ k = indices.back(); } dp[i][j] += h[i][j] * (j - k); if(k != -1){ if(a[i][k] == a[i][j]){ dp[i][j] += dp[i][k]; } } indices.push_back(j); } } return dp; } void solve() { int n, m; cin >> n >> m; vector<vector<int>> a(n, vector<int>(m)); for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ cin >> a[i][j]; } } vector<vector<ll>> dp = get_number_of_rectangles(a, n, m); ll ans = 0; for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ ans += dp[i][j]; } } cout << ans << '\n'; }
  • Vote: I like it
  • +8
  • Vote: I do not like it

»
9 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by one_autum_leaf (previous revision, new revision, compare).

»
9 months ago, # |
  Vote: I like it 0 Vote: I do not like it

starred and upvoted ! <3

»
9 months ago, # |
  Vote: I like it 0 Vote: I do not like it

This can also be solved in $$$\mathcal{O}(nm)$$$ with a method similar to CSES — Maximum Building II by enumerating the row of the bottom edge of the submatrix and using stacks to count the number of submatricies.

»
9 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Can you clarify the statement? Do you mean rectangles or do you really mean matrices that can be formed by deleting some rows and columns?

A B A
C C C
A B A

The result with the first interpretation is 12, but using the second interpretation it's 19 I think (for example, you can form a matrix full of As by deleting the 2nd row and the 2nd column).

  • »
    »
    9 months ago, # ^ |
      Vote: I like it +5 Vote: I do not like it

    Sorry for the confusion. I meant rectangles that can be formed by considering a continuous range of columns and rows. Basically submatrices.

»
9 months ago, # |
  Vote: I like it 0 Vote: I do not like it

Auto comment: topic has been updated by one_autum_leaf (previous revision, new revision, compare).