Pond
Pista
Hay que hallar una formulación para comprobar si la mediana de un cuadrado es menor o igual que .
Explicación
Solución
Para resolver este problema, hacemos búsqueda binaria sobre la respuesta. Para un valor dado , preguntamos si existe una región cuya mediana es menor o igual que . Según las respuestas a estas preguntas, actualizamos el rango de la búsqueda binaria y calculamos la mediana más baja entre todos los parques.
Ahora nos concentramos en cómo comprobar de forma eficiente si existe tal cuadrado . Construimos un arreglo en el que cada casilla tiene si y en caso contrario. Como se muestra en el módulo de sumas de prefijos 2D, podemos calcular las sumas de prefijos 2D de y usarlas para determinar de forma eficiente si las casillas que cumplen forman una mayoría dentro de alguna región .
Sea la suma de las entradas en la región de a . Entonces, la suma de una región con esquina inferior derecha en sería
Como cada entrada con valor a lo sumo contribuye y en caso contrario, la suma representa la cantidad de casillas con valor menor o igual que menos la cantidad de casillas cuyo valor es mayor que dentro de la región.
Si alguna región tiene suma neta mayor o igual que , entonces es posible una mediana de a lo sumo , y la prueba fue exitosa. En caso contrario, hay que considerar valores más grandes de en la búsqueda binaria.
Implementación
Complejidad temporal:
Código de la solución
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<vector<int>> a(n, vector<int>(n));
vector<vector<int>> p(n + 1, vector<int>(n + 1));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) { cin >> a[i][j]; }
}
int lo = 0, hi = 1e9;
while (lo <= hi) {
int mid = (lo + hi) / 2;
// Construimos el arreglo de prefijos 2D
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
p[i][j] = p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1];
p[i][j] += (a[i - 1][j - 1] <= mid) ? 1 : -1;
}
}
// Calculamos las regiones K x K
bool found = false;
for (int i = k; i <= n; i++) {
for (int j = k; j <= n; j++) {
int vl = p[i][j] - p[i - k][j] - p[i][j - k] + p[i - k][j - k];
if (vl >= 0) {
found = true;
break;
}
}
if (found) break;
}
if (found) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
cout << lo << '\n';
}