Just Green Enough
Explicación
Primero, consideremos resolver este problema en 1D, donde elegimos intervalos de la lista , los valores de un pasto de .
Sea igual a si , si , y si . Debemos hallar un rango de en el que no haya y haya al menos un . Precomputamos . El objetivo ahora es contar la cantidad de intervalos sin y con al menos un .
Luego, barreemos de a y llevamos el último índice en el que encontramos y como y , respectivamente. Para que un intervalo se elija, debe incluir un , así que el índice inicial no puede ser posterior al último que encontramos; el intervalo no puede incluir un , así que el índice inicial debe ser posterior al último que encontramos. Así, cualquier rango con índice inicial en el intervalo e índice final en funciona, siempre que y . Hay intervalos; acumulamos esos números si se cumplen las condiciones para obtener la respuesta. Inicializamos tanto como en , de modo que al principio no produzcan acumulación, y que todas las posibilidades de se cuenten si todavía no ha aparecido un .
Ahora generalizamos esto a dos dimensiones, donde elegimos subrectángulos de un pasto de . Denotamos los valores del pasto para . Primero consideramos los casos en los que los bordes del rectángulo incluyen e , 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 para seguir la viabilidad del extremo izquierdo por columna. Cualquier elemento de una columna bloquea la selección, y cualquier elemento la permite, así que se marca o si estas condiciones se cumplen para algún elemento de una columna, y en caso contrario. Luego procedemos como en el caso 1D para .
Ahora generalizamos al caso en que el subrectángulo puede tener bordes verticales arbitrarios e . De forma naive, procederíamos como en el caso anterior, usando solo los elementos en de cada columna para calcular ; sin embargo, recalcular cada vez es demasiado ineficiente. Por eso usamos un enfoque incremental: En cada posible, reiniciamos a s, antes de recorrer y . En cada , da cuenta de , así que lo actualizamos para dar cuenta de en cada antes de usar el enfoque anterior. Llevar el arreglo de forma acumulativa nos da complejidad por cada elección de filas superior e inferior, así que en total tenemos .
Implementación
Complejidad temporal:
#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;
}