Skip to Content

Just Green Enough

Análisis oficial (C++, Java) 

Explicación

Primero, consideremos resolver este problema en 1D, donde elegimos intervalos de la lista g(j)g(j), los valores de un pasto de 1×N1\times N.

Sea g(j)g'(j) igual a 1-1 si g(j)<100g(j)<100, 00 si g(j)=100g(j)=100, y 11 si g(j)>100g(j)>100. Debemos hallar un rango de jj en el que no haya 1-1 y haya al menos un 00. Precomputamos g(j)g'(j). El objetivo ahora es contar la cantidad de intervalos sin 1-1 y con al menos un 00.

Luego, barreemos jj de 11 a NN y llevamos el último índice en el que encontramos 00 y 1-1 como j0j_0 y j1j_{-1}, respectivamente. Para que un intervalo se elija, debe incluir un 00, así que el índice inicial no puede ser posterior al último 00 que encontramos; el intervalo no puede incluir un 1-1, así que el índice inicial debe ser posterior al último 1-1 que encontramos. Así, cualquier rango con índice inicial en el intervalo (j1,j0](j_{-1}, j_0] e índice final en jj funciona, siempre que j1<j0j_{-1}<j_0 y g(j){0,1}g'(j)\in\{0,1\}. Hay j0j1j_0-j_{-1} intervalos; acumulamos esos números si se cumplen las condiciones para obtener la respuesta. Inicializamos tanto j0j_0 como j1j_{-1} en 00, de modo que al principio no produzcan acumulación, y que todas las posibilidades de (0,j0](0, j_0] se cuenten si todavía no ha aparecido un 1-1.

Ahora generalizamos esto a dos dimensiones, donde elegimos subrectángulos de un pasto de N×NN\times N. Denotamos los valores del pasto G(i,j)G(i, j) para i,j[1,N]i,j\in[1,N]. Primero consideramos los casos en los que los bordes del rectángulo incluyen i=1i=1 e i=Ni=N, y nos queda elegir el intervalo para los bordes izquierdo y derecho. Como en el caso 1D, barreemos de izquierda a derecha el extremo derecho y construimos un gg' para seguir la viabilidad del extremo izquierdo por columna. Cualquier elemento <100<100 de una columna bloquea la selección, y cualquier elemento =100=100 la permite, así que gg' se marca 1-1 o 00 si estas condiciones se cumplen para algún elemento de una columna, y 11 en caso contrario. Luego procedemos como en el caso 1D para gg'.

Ahora generalizamos al caso en que el subrectángulo puede tener bordes verticales arbitrarios i=i1i=i_1 e i=i2i1i=i_2\geq i_1. De forma naive, procederíamos como en el caso anterior, usando solo los elementos en i[i1,i2]i\in[i_1,i_2] de cada columna para calcular gg'; sin embargo, recalcular gg' cada vez es demasiado ineficiente. Por eso usamos un enfoque incremental: En cada i1i_1 posible, reiniciamos g(j)g'(j) a 11s, antes de recorrer i2i_2 y jj. En cada i2i_2, g(j)g'(j) da cuenta de G(i1i21,j)G(i_1\ldots i_2-1,j), así que lo actualizamos para dar cuenta de G(i2,j)G(i_2,j) en cada jj antes de usar el enfoque anterior. Llevar el arreglo gg' de forma acumulativa nos da complejidad O(N)\mathcal O(N) por cada elección de filas superior e inferior, así que en total tenemos O(N3)\mathcal O(N^3).

Implementación

Complejidad temporal: O(N3)\mathcal O(N^3)

#include <iostream> using namespace std; constexpr int MAX_N = 500; // G en el problema int a[MAX_N + 1][MAX_N + 1]; // g' en la explicación int g_prime[MAX_N + 1]; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> a[i][j]; long long ans = 0; for (int i1 = 1; i1 <= n; i1++) { // Reiniciar g' for (int j = 1; j <= n; j++) g_prime[j] = 1; for (int i2 = i1; i2 <= n; i2++) { // i_0 e i_{-1} en la explicación, respectivamente int last_zero = 0, last_neg = 0; for (int j = 1; j <= n; j++) { // Actualizar g' if (a[i2][j] < 100) g_prime[j] = -1; if (a[i2][j] == 100 && g_prime[j] != -1) g_prime[j] = 0; // Actualizar últimos índices if (g_prime[j] == 0) last_zero = j; if (g_prime[j] == -1) last_neg = j; // Acumular if (g_prime[j] == 0 || g_prime[j] == 1) { ans += max(0, last_zero - last_neg); } } } } cout << ans << endl; return 0; }