Skip to Content

Commando

Explicación

Sea dp[i]\texttt{dp}[i] la efectividad máxima del prefijo de longitud ii de la unidad. Las transiciones se definen como dp[i]=max0j<i{dp[j]+ax2+bx+c}\texttt{dp}[i] = \max_{0 \leq j < i} \{\texttt{dp}[j] + ax^2+bx+c\}, donde x=sum(j+1,i)=k=j+1ixkx = \texttt{sum}(j + 1, i) = \sum_{k = j + 1}^i x_k.

Definimos un arreglo de sumas de prefijos pre[i]=k=1ixk\texttt{pre}[i] = \sum_{k = 1}^i x_k. Entonces podemos expresar xx como pre[i]pre[j]\texttt{pre}[i] - \texttt{pre}[j]. Ahora evaluamos la primera ecuación con nuestro nuevo valor de xx:

  • dp[i]=max1j<i{dp[j]+ax2+bx+c}\texttt{dp}[i] = \max_{1 \leq j < i} \{\texttt{dp}[j] + ax^2+bx+c\}
  • dp[i]=max1j<i{dp[j]+a[pre[i]pre[j]]2+b[pre[i]pre[j]]+c}\texttt{dp}[i] = \max_{1 \leq j < i} \{\texttt{dp}[j] + a[\texttt{pre}[i] - \texttt{pre}[j]]^2+b[\texttt{pre}[i] - \texttt{pre}[j]]+c\}
  • dp[i]=max1j<i{dp[j]+[apre[i]22apre[i]pre[j]+apre[j]2]+bpre[i]bpre[j]+c}\texttt{dp}[i] = \max_{1 \leq j < i} \{\texttt{dp}[j] + [a\cdot\texttt{pre}[i]^2 - 2a\cdot\texttt{pre}[i]\texttt{pre}[j] + a\cdot\texttt{pre}[j]^2] + b\cdot\texttt{pre}[i]-b\cdot\texttt{pre}[j]+c\}

Sacamos fuera del max\max los términos que no dependen de jj.

dp[i]=max0j<i{dp[j]2apre[i]pre[j]+apre[j]2bpre[j]}+apre[i]2+bpre[i]+c\texttt{dp}[i] = \max_{0 \leq j < i} \{\texttt{dp}[j] - 2a\cdot\texttt{pre}[i]\texttt{pre}[j] + a\cdot\texttt{pre}[j]^2 - b\cdot\texttt{pre}[j]\} + a\cdot\texttt{pre}[i]^2 + b\cdot\texttt{pre}[i] + c

Agrupamos con dp[j]\texttt{dp}[j] los términos que dependen solo de jj.

dp[i]=max0j<i{(dp[j]+apre[j]2bpre[j])2apre[i]pre[j]}+apre[i]2+bpre[i]+c\texttt{dp}[i] = \max_{0 \leq j < i} \{(\texttt{dp}[j] + a\cdot\texttt{pre}[j]^2 - b\cdot\texttt{pre}[j]) - 2a\cdot\texttt{pre}[i]\texttt{pre}[j]\} + a\cdot\texttt{pre}[i]^2 + b\cdot\texttt{pre}[i] + c

Para manejar las transiciones de forma eficiente en O(logn)\mathcal{O}(\log n) o O(1)\mathcal{O}(1), usamos la optimización de envolvente convexa.

Complejidad temporal: O(nlogn)\mathcal{O}(n \log n)

Implementación

#include <bits/stdc++.h> using namespace std; // source: // https://github.com/kth-competitive-programming/kactl/blob/main/content/data-structures/LineContainer.h // supports insertion of linear functions and querying of MAXIMUM value of x for // a given x for details on internal implementation, see LineContainer module // alternatively, learn Li Chao Tree inline namespace _LineContainer { bool _Line_Comp_State; struct Line { // k is slope, m is intercept, p is intersection point mutable ll k, m, p; bool operator<(const Line &o) const { return _Line_Comp_State ? p < o.p : k < o.k; } }; struct LineContainer : multiset<Line> { long long div(long long a, long long b) { return a / b - ((a ^ b) < 0 && a % b); } bool isect(iterator x, iterator y) { if (y == end()) { x->p = LLONG_MAX; return false; } if (x->k == y->k) x->p = x->m > y->m ? LLONG_MAX : -LLONG_MAX; else x->p = div(y->m - x->m, x->k - y->k); return x->p >= y->p; } void add(long long k, long long m) { auto z = insert({k, m, 0}), y = z++, x = y; while (isect(y, z)) z = erase(z); if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y)); } long long query(long long x) { assert(!empty()); _Line_Comp_State = 1; auto l = *lower_bound({0, 0, x}); _Line_Comp_State = 0; return l.k * x + l.m; } }; } // namespace _LineContainer long long N, A, B, C; LineContainer lc; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> N >> A >> B >> C; long long P = 0, a, dp = 0; for (int i = 1; i <= N; i++) { lc.add(-2 * A * P, dp + A * P * P - B * P); cin >> a; P += a; dp = lc.query(P) + A * P * P + B * P + C; } cout << dp << '\n'; }