|
| 1 | +--- |
| 2 | +id: kilonova-ssdj |
| 3 | +source: Romania IOI selection test 2014 |
| 4 | +title: ssdj |
| 5 | +author: Stefan Dascalescu |
| 6 | +--- |
| 7 | + |
| 8 | +[Official Analysis (in Romanian)](https://github.com/roalgo-discord/Romanian-Olympiad-Solutions/blob/main/Baraj%20%2B%20Lot%20Seniori%20(IOI%20team%20selection%20tests)/2014/Lot%201/sol-ssdj.pdf) |
| 9 | + |
| 10 | +## Explanation |
| 11 | + |
| 12 | +Let's start from a more simple case, when the grid will only contain letters `a` and `b`. Let's associate for each letter a value corresponding to its position in the alphabet (for now, `a` equals $0$ and `b` equals $1$). Now we will have to find the number of submatrices such that we have ones in the top left and bottom right corners we have $1$ and we have $0$ everywhere else. |
| 13 | + |
| 14 | +Let's construct another grid of size $n \times n$ where $b(i, j)$ stores the number of consecutive $0$ on the column $j$ above the position $(i, j)$. |
| 15 | + |
| 16 | +Now for each line from $2$ to $n$, for a given position $(i, j)$ which is equal to $1$ (we will consider this the bottom-right corner), we will move from right to left on that line to find the values equal to $1$ placed at coordinates $(i, k)$ where $k < j$ such that $b(i, k) > 0$ and $b(i, k)$ strictly smaller than all values $b(i, p)$ with $p$ between $k+1$ and $j$. |
| 17 | + |
| 18 | +The complexity of this approach is $\mathcal{O}(n^2)$. |
| 19 | + |
| 20 | +Now we need to generalize for the entire grid, which has all lowercase letters of the alphabet. At each step, we fix a letter, let's call it $ch$. |
| 21 | + |
| 22 | +For that letter, we will now create a grid where the positions corresponding to all the letters which are smaller than $ch$ will be equal to $0$, all letters equal to $ch$ will be equal to $1$ and all letters greater than $ch$ will be equal to $2$. |
| 23 | + |
| 24 | +Just like we did it for the binary grid, we will count how many submatrices have values equal to $0$ except for the two corners aforementioned. In order to avoid overcounting, we will only count the submatrices such that they contain $1$ in at least a corner. Now, when we process a position $(i, j)$ we will do as such: if on that position we have $1$, we will count the number of previous position which correspond to both $1$ and $2$, and if on the same position we have $2$, we will only count the previous positions that are equal to $1$. |
| 25 | + |
| 26 | +The complexity of this approach is still $\mathcal{O}(n^2)$ for each letter, which gives us an overall complexity of $\mathcal{O}(sigma \times n^2)$, where $sigma = 26$ is the length of the alphabet. |
| 27 | + |
| 28 | +For other approaches, you can also check out the user solutions on [Infoarena](https://infoarena.ro/monitor?task=ssdj), just make sure to press that popup you receive after you first click on a solution. |
| 29 | + |
| 30 | +## Implementation |
| 31 | + |
| 32 | +**Time Complexity:** $\mathcal{O}(26 \cdot N^2)$ |
| 33 | + |
| 34 | +<LanguageSection> |
| 35 | +<CPPSection> |
| 36 | + |
| 37 | +```cpp |
| 38 | +#include <bits/stdc++.h> |
| 39 | +using namespace std; |
| 40 | + |
| 41 | +int main() { |
| 42 | + ifstream f("ssdj.in"); |
| 43 | + |
| 44 | + int n; |
| 45 | + f >> n; |
| 46 | + |
| 47 | + long long ans = 0; |
| 48 | + vector<vector<char>> mat(n + 1, vector<char>(n + 1)); |
| 49 | + vector<vector<int>> lst(n + 2, vector<int>(n + 2)); |
| 50 | + vector<vector<int>> lst2(n + 2, vector<int>(n + 2)); |
| 51 | + vector<int> d(n + 2); |
| 52 | + |
| 53 | + for (int i = 1; i <= n; i++) { |
| 54 | + for (int j = 1; j <= n; j++) { f >> mat[i][j]; } |
| 55 | + } |
| 56 | + for (int i = 1; i <= n; i++) { lst2[n + 1][i] = n + 2; } |
| 57 | + for (char i = 'z'; i >= 'a'; i--) { |
| 58 | + for (int row = 1; row <= n; row++) { |
| 59 | + int stackSize = 0; |
| 60 | + for (int col = 1; col <= n; col++) { |
| 61 | + if (mat[row][col] >= i) { |
| 62 | + lst[row][col] = row; |
| 63 | + } else { |
| 64 | + lst[row][col] = lst[row - 1][col]; |
| 65 | + } |
| 66 | + while (stackSize && |
| 67 | + lst[row - 1][col] >= lst[row][d[stackSize]]) { |
| 68 | + --stackSize; |
| 69 | + } |
| 70 | + if (mat[row][col] == i) { |
| 71 | + ans += stackSize; |
| 72 | + if (stackSize && d[1] == col) { --stackSize; } |
| 73 | + } |
| 74 | + while (stackSize && lst[row][col] >= lst[row][d[stackSize]]) { |
| 75 | + --stackSize; |
| 76 | + } |
| 77 | + if (lst[row][col] <= (row - 1) && lst[row][col] != 0) { |
| 78 | + d[++stackSize] = col; |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + for (int row = n; row >= 1; row--) { |
| 84 | + int stackSize = 0; |
| 85 | + int hm = 0; |
| 86 | + for (int col = n; col >= 1; col--) { |
| 87 | + if (mat[row][col] >= i) { |
| 88 | + lst2[row][col] = row; |
| 89 | + } else { |
| 90 | + lst2[row][col] = lst2[row + 1][col]; |
| 91 | + } |
| 92 | + while (stackSize && |
| 93 | + lst2[row + 1][col] <= lst2[row][d[stackSize]]) { |
| 94 | + if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) { |
| 95 | + hm--; |
| 96 | + } |
| 97 | + stackSize--; |
| 98 | + } |
| 99 | + if (mat[row][col] == i) { |
| 100 | + ans += stackSize; |
| 101 | + ans -= hm; |
| 102 | + if (stackSize && d[stackSize] == col) { ans--; } |
| 103 | + } |
| 104 | + while (stackSize && lst2[row][col] <= lst2[row][d[stackSize]]) { |
| 105 | + if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) { |
| 106 | + hm--; |
| 107 | + } |
| 108 | + stackSize--; |
| 109 | + } |
| 110 | + if (lst2[row][col] >= (row + 1) && lst2[row][col] != (n + 2)) { |
| 111 | + if (mat[lst2[row][col]][col] == i) { hm++; } |
| 112 | + d[++stackSize] = col; |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + ofstream("ssdj.out") << ans << endl; |
| 119 | +} |
| 120 | +``` |
| 121 | +
|
| 122 | +</CPPSection> |
| 123 | +</LanguageSection> |
0 commit comments