Max Median
Explicación
Podemos hacer búsqueda binaria sobre la mayor mediana posible de alcanzar.
Para comprobar si la mediana es alcanzable en un intervalo, necesitamos contar el número de elementos que son y el número de elementos que son .
Si el número de elementos es mayor que el número de elementos , podemos decir que esta mediana es alcanzable. Observemos que debe haber estrictamente más elementos mayores o iguales que que menores que por cómo el problema define la mediana para subarreglos de tamaño par.
Sea el número de elementos del prefijo que son menos el número de elementos del prefijo que son .
Podemos demostrar que si e , es posible tener una mediana de . Esto se debe a que en el rango de a habrá más elementos mayores o iguales que que menores que , lo que significa que la mediana también será mayor o igual que .
A partir de aquí podemos hacer una búsqueda lineal de la diferencia máxima, llevando el registro del elemento mínimo del prefijo de a , lo que asegura que el tamaño sea siempre al menos . Si es mayor que , entonces esta mediana es posible de alcanzar.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int &i : a) { cin >> i; }
// Búsqueda binaria de la mediana máxima
int lo = 1;
int hi = n;
while (lo < hi) {
int median = (lo + hi + 1) / 2;
// Igual que la f descrita en la editorial
vector<int> f(n);
for (int i = 0; i < n; i++) {
/*
* Si a[i] es mayor o igual que la mediana,
* aporta 1 a f(i). En caso contrario, si es menor que la mediana,
* aporta -1 a f(i)
*/
f[i] = a[i] >= median ? 1 : -1;
if (i) { f[i] += f[i - 1]; }
}
// Lleva el registro del valor mínimo de f(x) en el prefijo
int mn = 0;
int diff = 0;
// Iterar sobre el puntero final de un subarreglo.
for (int i = k - 1; i < n; i++) {
// Actualizar el elemento mínimo del prefijo.
mn = min(mn, f[i - k]);
// Actualizar la diferencia máxima posible.
diff = max(diff, f[i] - mn);
}
// Actualizar las cotas de la búsqueda binaria.
if (diff > 0) {
lo = median;
} else {
hi = median - 1;
}
}
cout << lo << endl;
}import java.io.*;
import java.util.*;
public class MaxMedian {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw = new PrintWriter(System.out);
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
st = new StringTokenizer(br.readLine());
int[] a = new int[n];
for (int i = 0; i < n; i++) { a[i] = Integer.parseInt(st.nextToken()); }
// Búsqueda binaria de la mediana máxima
int lo = 1;
int hi = n;
while (lo < hi) {
int median = (lo + hi + 1) / 2;
// Igual que la f descrita en la editorial
int[] f = new int[n];
for (int i = 0; i < n; i++) {
/*
* Si a[i] es mayor o igual que la mediana,
* aporta 1 a f(i). En caso contrario, si es menor que la mediana,
* aporta -1 a f(i)
*/
f[i] = a[i] >= median ? 1 : -1;
if (i > 0) { f[i] += f[i - 1]; }
}
// Lleva el registro del valor mínimo de f(x) en el prefijo
int mn = 0;
int diff = 0;
// Iterar sobre el puntero final de un subarreglo.
for (int i = k - 1; i < n; i++) {
// Actualizar el elemento mínimo del prefijo.
if (i - k >= 0) { mn = Math.min(mn, f[i - k]); }
// Actualizar la diferencia máxima posible.
diff = Math.max(diff, f[i] - mn);
}
// Actualizar las cotas de la búsqueda binaria.
if (diff > 0) {
lo = median;
} else {
hi = median - 1;
}
}
pw.println(lo);
pw.close();
}
}n, k = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
# Búsqueda binaria sobre la mediana máxima
lo = 1
hi = n
while lo < hi:
median = (lo + hi + 1) // 2
# Igual que la f descrita en la editorial
f = []
for i in range(n):
# Si a[i] es mayor o igual que la mediana, aporta 1 a f(i)
# En caso contrario, si es menor que la mediana, aporta -1 a f(i)
f.append(1 if a[i] >= median else -1)
if i > 0:
f[i] += f[i - 1]
# Lleva el registro del valor mínimo de f(x) en el prefijo
mn = 0
diff = 0
# Iterar sobre el puntero final de un subarreglo.
for i in range(k - 1, n):
# Actualizar el elemento mínimo del prefijo.
if i - k >= 0:
mn = min(mn, f[i - k])
# Actualizar la diferencia máxima posible.
diff = max(diff, f[i] - mn)
# Actualizar las cotas de la búsqueda binaria.
if diff > 0:
lo = median
else:
hi = median - 1
print(lo)