Truco de la envolvente convexa
Queremos resolver problemas de la siguiente forma:
Considerar un conjunto de funciones sobre algún rango tal que para cualesquiera dos funciones y existe algún tal que
- Para todo ,
- Para todo ,
Responder consultas de la forma “cuál es el máximo/mínimo para algún dado”, suponiendo que tenemos una forma de hallar de manera eficiente.
Un conjunto de condiciones suficiente (pero no necesario):
- Todas las funciones son continuas a lo largo del rango .
- Ningún par de funciones se intersecta en más de un punto.
El caso más común es cuando cada es de la forma . Dadas dos rectas y tales que , su punto de intersección se puede hallar en tiempo . Entonces es claro que
- Para todo , .
- Para todo , .
El caso lineal se conoce como el truco de la envolvente convexa (convex hull trick, CHT) porque como función de es cóncava hacia arriba (de forma análoga, como función de es cóncava hacia abajo). Ver las imágenes del tutorial de CF de abajo si esto no queda claro.
Algunas formas no lineales posibles de :
-
- Se reduce al caso lineal, ya que podemos ignorar el término al comparar dos funciones.
-
- Si esta función está definida para todo .
- Observar que cuando , es estrictamente decreciente sobre el rango .
En este módulo nos concentramos en el caso especial de CHT en el que las
“pendientes” de las funciones son monótonas. Este caso específico se puede
resolver en usando un std::deque en C++. Para el CHT más
general en (que involucra un std::multiset), ver
el módulo LineContainer.
| Hecho | Fuente | Nombre | Dificultad | Tags | Solución |
|---|---|---|---|---|---|
| CF | The Fair Nut and Rectangles | Fácil | DP, Convex | en el módulo |
Tutorial
| Fuente | Recurso | Notas |
|---|---|---|
| CF | Convex Hull Trick - Geo Being Useful | resuelve el problema de arriba |
| GCP | 15.4.1 - Convex Hull Trick | |
| Jeffrey Xiao | Convex Hull Trick |
Solución - The Fair Nut and Rectangles
No voy a analizar este problema en gran detalle porque el blog de Codeforces de los recursos ya lo hace, pero esencialmente ordenamos los rectángulos por coordenada y obtenemos la siguiente recurrencia de DP:
Observar cómo la parte de la recurrencia describe una recta .
Como ordenamos los rectángulos y ningún par de rectángulos está anidado, las pendientes de las rectas que insertamos son estrictamente crecientes. Las posiciones de consulta también son estrictamente crecientes.
Esto significa que podemos resolver este problema usando CHT en tiempo . Acá está mi implementación:
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
struct Rect {
ll x, y, a;
bool operator<(Rect B) { return x < B.x; }
};
Rect a[1000001];
ll dp[1000001];
double slope(int i, int j) { return (double)(dp[i] - dp[j]) / (a[i].x - a[j].x); }
int main() {
iostream::sync_with_stdio(false);
cin.tie(0);
ll n;
cin >> n;
for (int i = 1; i <= n; i++) { cin >> a[i].x >> a[i].y >> a[i].a; }
sort(a + 1, a + n + 1);
deque<ll> q;
q.push_back(0);
for (int i = 1; i <= n; i++) {
while (q.size() > 1 && slope(q[0], q[1]) >= a[i].y) q.pop_front();
ll j = q.front();
dp[i] = max(dp[i - 1], a[i].x * a[i].y - a[i].a + dp[j] - a[j].x * a[i].y);
while (q.size() > 1 && slope(q[q.size() - 2], q.back()) <= slope(q.back(), i))
q.pop_back();
q.push_back(i);
}
cout << dp[n];
return 0;
}Problemas
| Hecho | Fuente | Nombre | Dificultad | Tags | Solución |
|---|---|---|---|---|---|
| APIO | 2010 - Commando | Fácil | DP, Convex | Solución | |
| CEOI | 2004 - Two Sawmills | Fácil | DP, Convex | Solución | |
| CSES | Houses and Schools | Fácil | DP, Convex | Solución | |
| CEOI | 2009 - Harbingers | Normal | DP, Convex | Solución | |
| CF | Bear and Bowling 4 | Normal | D&C, DP | Solución | |
| IOI | 2002 - Batch Scheduling | Normal | DP, Convex | Solución | |
| APIO | 2014 - Split the Sequence | Normal | DP, Convex | Solución | |
| POI | 2011 - Lightning Conductor | Normal | DP, Convex | Solución | |
| POI | 2006 - Frogs | Normal | DP, Convex | — | |
| Platinum | Circular Barn | Normal | DP, Convex | Solución | |
| Platinum | Falling Portals | Normal | Convex | — | |
| Platinum | Mana Collection | Difícil | Bitmask DP, Convex | Solución | |
| JOI | 2017 - Long-Distance Coach | Difícil | DP, Convex | — |