Skip to Content

Sabotage

Análisis oficial (C++) 

Explicación

Podemos hacer búsqueda binaria sobre valores reales para hallar el promedio mínimo XX que podemos lograr.

Ahora, si hallamos el arreglo de sumas de prefijos pref\texttt{pref} del arreglo de producción de leche MM, consideremos la condición que necesitamos para lograr un promedio X\le X al quitar el subarreglo (i,j](i, j]:

S(pref[j]pref[i])N(ji)X, \frac{S-\left(\texttt{pref}[j]-\texttt{pref}[i]\right)}{N-\left(j-i\right)}\le X,

donde SS es la suma actual del arreglo. Tras multiplicar ambos lados por el denominador y aislar todos los términos que involucran a ii, obtenemos:

pref[i]XiX(Nj)S+pref[j]. \texttt{pref}[i]-X\cdot i\le X\cdot\left(N-j\right)-S+\texttt{pref}[j].

Para un jj fijo, deberíamos intentar minimizar la expresión del lado izquierdo. Así que podemos iterar jj de 22 a N1N - 1 y mantener un mínimo corriente del lado izquierdo de la desigualdad. Si la condición se cumple, podemos lograr un promedio X\le X.

Implementación

Complejidad temporal: O(Nlog(1ε))\mathcal{O}(N\log\left(\frac{1}{\varepsilon}\right)), donde ε\varepsilon 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"))