Sabotage
Explicación
Podemos hacer búsqueda binaria sobre valores reales para hallar el promedio mínimo que podemos lograr.
Ahora, si hallamos el arreglo de sumas de prefijos del arreglo de producción de leche , consideremos la condición que necesitamos para lograr un promedio al quitar el subarreglo :
donde es la suma actual del arreglo. Tras multiplicar ambos lados por el denominador y aislar todos los términos que involucran a , obtenemos:
Para un fijo, deberíamos intentar minimizar la expresión del lado izquierdo. Así que podemos iterar de a y mantener un mínimo corriente del lado izquierdo de la desigualdad. Si la condición se cumple, podemos lograr un promedio .
Implementación
Complejidad temporal: , donde es el margen de error fijo.
#include <bits/stdc++.h>
using namespace std;
int main() {
freopen("sabotage.in", "r", stdin);
freopen("sabotage.out", "w", stdout);
int n;
cin >> n;
vector<int> m(n);
for (int i = 0; i < n; i++) cin >> m[i];
// Sumas de prefijos del arreglo de producción de leche m
vector<long long> pref_sum(n + 1);
for (int i = 0; i < n; i++) { pref_sum[i + 1] = pref_sum[i] + m[i]; }
long long arr_sum = pref_sum[n];
// Función de verificación para ver si se puede lograr el promedio x
auto check = [&](double x) {
double left_side = pref_sum[1] - x;
for (int j = 2; j <= n - 1; j++) {
double right_side = x * (n - j) - arr_sum + pref_sum[j];
if (left_side <= right_side) { return true; }
left_side = min(left_side, pref_sum[j] - x * j);
}
return false;
};
double l = 1, r = 10000;
while (r - l > 1e-4) {
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
cout << fixed << setprecision(3) << l << "\n";
}with open("sabotage.in", "r") as read:
n = int(read.readline())
m = [int(read.readline()) for i in range(n)]
pref_sum = [0]
for i in range(n):
pref_sum.append(pref_sum[-1] + m[i])
arr_sum = sum(m)
def check(x):
left_side = pref_sum[1] - x
for j in range(2, n):
right_side = x * (n - j) - arr_sum + pref_sum[j]
if left_side <= right_side:
return True
left_side = min(left_side, pref_sum[j] - x * j)
return False
l, r = 1, 10000
while r - l > 1e-4:
mid = (l + r) / 2
if check(mid):
r = mid
else:
l = mid
print(f"{l:.3f}", file=open("sabotage.out", "w"))