Gap
Subtarea 1
Podemos hallar el mínimo y el máximo de en algún rango
simplemente consultando MinMax(l, r, &mn, &mx). Esto nos permite ir recortando
el rango y reconstruir con .
Luego recorremos y hallamos el mayor hueco.
Subtarea 2
No necesariamente hay que reconstruir por completo para hallar el mayor hueco. Observemos que si conocemos una cota inferior de la respuesta y el rango de todos los , entonces podemos consultar el rango en bloques de tamaño para hallar la respuesta. Esto funciona porque el mayor hueco siempre cubrirá al menos dos bloques.
¿Cuál es entonces la cota inferior de la respuesta? Si hay elementos que cubren un rango de tamaño , entonces la cota inferior es por el principio del palomar. (Esta es una idea similar a la solución de IMO 2020 P6).
Nuestro algoritmo queda así:
- Hallar el rango que cubre en 1 consulta. Esto contribuye a .
- Hallar (la cota inferior de la respuesta) con la fórmula de arriba.
- Consultar el rango en bloques de tamaño . Como hay de estos bloques y cada está incluido en exactamente 1 de estos bloques, esto contribuye a .
Esto nos permite hallar el mayor hueco con .
Implementación
#include "gap.h"
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 1e18;
ll a[100000], j = 0;
ll findGap(int T, int N) {
if (T == 1) {
ll l = 1, r = MAXN;
ll mn, mx;
vector<ll> v;
for (ll i = 0; i < (N + 1) / 2; i++) {
MinMax(l, r, &mn, &mx);
a[j++] = mn;
a[j++] = mx;
l = mn + 1, r = mx - 1;
}
sort(a, a + N);
ll ans = 0;
for (ll i = 0; i < N - 1; i++) ans = max(ans, a[i + 1] - a[i]);
return ans;
} else {
ll mn, mx;
MinMax(1, MAXN, &mn, &mx);
ll step = (mx - mn + N - 2) / (N - 1);
ll ans = step, x, y, l = mn, i;
for (i = mn; i + step < mx; i += step + 1) {
MinMax(i, i + step, &x, &y);
if (x != -1) {
ans = max(ans, x - l);
l = y;
}
}
MinMax(i, mx, &x, &y);
if (x != -1) ans = max(ans, x - l);
return ans;
}
}