Skip to Content

ssdj

Análisis oficial (en rumano) 

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 00 y b vale 11). Ahora tendremos que hallar la cantidad de submatrices tales que en las esquinas superior izquierda e inferior derecha tenemos 11 y tenemos 00 en todos los demás lugares.

Construyamos otra grilla de tamaño n×nn \times n donde b(i,j)b(i, j) guarda la cantidad de 00 consecutivos en la columna jj por encima de la posición (i,j)(i, j).

Ahora, para cada fila de 22 a nn, para una posición dada (i,j)(i, j) que es igual a 11 (consideraremos esta la esquina inferior derecha), nos moveremos de derecha a izquierda en esa fila para hallar los valores iguales a 11 ubicados en coordenadas (i,k)(i, k) donde k<jk < j tales que b(i,k)>0b(i, k) > 0 y b(i,k)b(i, k) es estrictamente menor que todos los valores b(i,p)b(i, p) con pp entre k+1k+1 y jj.

La complejidad de este enfoque es O(n2)\mathcal{O}(n^2).

Ahora necesitamos generalizar para toda la grilla, que tiene todas las letras minúsculas del alfabeto. En cada paso, fijamos una letra, llamémosla chch.

Para esa letra, crearemos ahora una grilla donde las posiciones correspondientes a todas las letras que son menores que chch serán iguales a 00, todas las letras iguales a chch serán iguales a 11 y todas las letras mayores que chch serán iguales a 22.

Al igual que hicimos para la grilla binaria, contaremos cuántas submatrices tienen valores iguales a 00 excepto por las dos esquinas mencionadas. Para evitar el sobreconteo, solo contaremos las submatrices tales que contienen 11 en al menos una esquina. Ahora, cuando procesamos una posición (i,j)(i, j) haremos lo siguiente: si en esa posición tenemos 11, contaremos la cantidad de posiciones previas que corresponden tanto a 11 como a 22, y si en la misma posición tenemos 22, solo contaremos las posiciones previas que son iguales a 11.

La complejidad de este enfoque sigue siendo O(n2)\mathcal{O}(n^2) por cada letra, lo que nos da una complejidad total de O(sigma×n2)\mathcal{O}(sigma \times n^2), donde sigma=26sigma = 26 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: O(26N2)\mathcal{O}(26 \cdot N^2)

#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; }