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 j−1j_{-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 (j−1,j0](j_{-1}, j_0] e índice final en jj funciona, siempre que j−1<j0j_{-1}<j_0 y g′(j)∈{0,1}g'(j)\in\{0,1\}. Hay j0−j−1j_0-j_{-1} intervalos; acumulamos esos números si se cumplen las condiciones para obtener la respuesta. Inicializamos tanto j0j_0 como j−1j_{-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 g′g' 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 g′g' 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 g′g'.

Ahora generalizamos al caso en que el subrectángulo puede tener bordes verticales arbitrarios i=i1i=i_1 e i=i2≥i1i=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 g′g'; sin embargo, recalcular g′g' 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(i1…i2−1,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 g′g' 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; }