ssdj
Explicación
Empecemos por un caso más simple, cuando la grilla solo contiene las letras a y b. Asociemos a cada letra un valor correspondiente a su posición en el alfabeto (por ahora, a vale y b vale ). Ahora tendremos que hallar la cantidad de submatrices tales que en las esquinas superior izquierda e inferior derecha tenemos y tenemos en todos los demás lugares.
Construyamos otra grilla de tamaño donde guarda la cantidad de consecutivos en la columna por encima de la posición .
Ahora, para cada fila de a , para una posición dada que es igual a (consideraremos esta la esquina inferior derecha), nos moveremos de derecha a izquierda en esa fila para hallar los valores iguales a ubicados en coordenadas donde tales que y es estrictamente menor que todos los valores con entre y .
La complejidad de este enfoque es .
Ahora necesitamos generalizar para toda la grilla, que tiene todas las letras minúsculas del alfabeto. En cada paso, fijamos una letra, llamémosla .
Para esa letra, crearemos ahora una grilla donde las posiciones correspondientes a todas las letras que son menores que serán iguales a , todas las letras iguales a serán iguales a y todas las letras mayores que serán iguales a .
Al igual que hicimos para la grilla binaria, contaremos cuántas submatrices tienen valores iguales a excepto por las dos esquinas mencionadas. Para evitar el sobreconteo, solo contaremos las submatrices tales que contienen en al menos una esquina. Ahora, cuando procesamos una posición haremos lo siguiente: si en esa posición tenemos , contaremos la cantidad de posiciones previas que corresponden tanto a como a , y si en la misma posición tenemos , solo contaremos las posiciones previas que son iguales a .
La complejidad de este enfoque sigue siendo por cada letra, lo que nos da una complejidad total de , donde es la longitud del alfabeto.
Para otros enfoques, también se pueden consultar las soluciones de usuarios en Infoarena ; solo hay que pulsar el popup que aparece después de hacer clic por primera vez en una solución.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
int main() {
ifstream f("ssdj.in");
int n;
f >> n;
long long ans = 0;
vector<vector<char>> mat(n + 1, vector<char>(n + 1));
vector<vector<int>> lst(n + 2, vector<int>(n + 2));
vector<vector<int>> lst2(n + 2, vector<int>(n + 2));
vector<int> d(n + 2);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) { f >> mat[i][j]; }
}
for (int i = 1; i <= n; i++) { lst2[n + 1][i] = n + 2; }
for (char i = 'z'; i >= 'a'; i--) {
for (int row = 1; row <= n; row++) {
int stackSize = 0;
for (int col = 1; col <= n; col++) {
if (mat[row][col] >= i) {
lst[row][col] = row;
} else {
lst[row][col] = lst[row - 1][col];
}
while (stackSize && lst[row - 1][col] >= lst[row][d[stackSize]]) {
--stackSize;
}
if (mat[row][col] == i) {
ans += stackSize;
if (stackSize && d[1] == col) { --stackSize; }
}
while (stackSize && lst[row][col] >= lst[row][d[stackSize]]) {
--stackSize;
}
if (lst[row][col] <= (row - 1) && lst[row][col] != 0) {
d[++stackSize] = col;
}
}
}
for (int row = n; row >= 1; row--) {
int stackSize = 0;
int hm = 0;
for (int col = n; col >= 1; col--) {
if (mat[row][col] >= i) {
lst2[row][col] = row;
} else {
lst2[row][col] = lst2[row + 1][col];
}
while (stackSize && lst2[row + 1][col] <= lst2[row][d[stackSize]]) {
if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) { hm--; }
stackSize--;
}
if (mat[row][col] == i) {
ans += stackSize;
ans -= hm;
if (stackSize && d[stackSize] == col) { ans--; }
}
while (stackSize && lst2[row][col] <= lst2[row][d[stackSize]]) {
if (mat[lst2[row][d[stackSize]]][d[stackSize]] == i) { hm--; }
stackSize--;
}
if (lst2[row][col] >= (row + 1) && lst2[row][col] != (n + 2)) {
if (mat[lst2[row][col]][col] == i) { hm++; }
d[++stackSize] = col;
}
}
}
}
ofstream("ssdj.out") << ans << endl;
}