Skip to content

Instantly share code, notes, and snippets.

@Chillee
Last active December 20, 2018 01:30
Show Gist options
  • Save Chillee/a96630c518b1505fd88ff5cc0abe0f1d to your computer and use it in GitHub Desktop.
Save Chillee/a96630c518b1505fd88ff5cc0abe0f1d to your computer and use it in GitHub Desktop.
Convex Hull Trick
struct Line {
mutable ll m, b, p;
bool operator<(const Line &o) const { return m < o.m; }
bool operator<(const ll &x) const { return p < x; }
};
struct LineContainer : multiset<Line, less<>> { // upper convex hull.
// (for doubles, use inf = 1/.0, div(a,b) = a/b)
const ll inf = LLONG_MAX;
ll div(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); }
bool isect(iterator x, iterator y) {
if (y == end()) {
x->p = inf;
return false;
}
if (x->m == y->m)
x->p = x->b > y->b ? inf : -inf;
else
x->p = div(y->b - x->b, x->m - y->m);
return x->p >= y->p;
}
void add(ll m, ll b) {
auto z = insert({m, b, 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));
}
ll query(ll x) {
assert(!empty());
auto l = *lower_bound(x);
return l.m * x + l.b;
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment