Alex_tz307

Dynamic Convex Hull

Feb 14th, 2021 (edited)
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 1.51 KB | None | 0 0
  1. using ll = long long;
  2.  
  3. const ll is_query = -(1LL<<62);
  4. struct line {
  5.     ll m, b;
  6.     mutable function<const line*()> succ;
  7.     bool operator<(const line& rhs) const {
  8.         if (rhs.b != is_query) return m < rhs.m;
  9.         const line* s = succ();
  10.         if (!s) return 0;
  11.         ll x = rhs.m;
  12.         return b - s->b < (s->m - m) * x;
  13.     }
  14. };
  15.  
  16. struct dynamic_hull : public multiset<line> { // will maintain upper hull for maximum
  17.     const ll inf = LLONG_MAX;
  18.     bool bad(iterator y) {
  19.         auto z = next(y);
  20.         if (y == begin()) {
  21.             if (z == end()) return 0;
  22.             return y->m == z->m && y->b <= z->b;
  23.         }
  24.         auto x = prev(y);
  25.         if (z == end()) return y->m == x->m && y->b <= x->b;
  26.  
  27.         /* compare two lines by slope, make sure denominator is not 0 */
  28.         ll v1 = (x->b - y->b);
  29.         if (y->m == x->m) v1 = x->b > y->b ? inf : -inf;
  30.         else v1 /= (y->m - x->m);
  31.         ll v2 = (y->b - z->b);
  32.         if (z->m == y->m) v2 = y->b > z->b ? inf : -inf;
  33.         else v2 /= (z->m - y->m);
  34.         return v1 >= v2;
  35.     }
  36.  
  37.     void insert_line(ll m, ll b) {
  38.         auto y = insert({ m, b });
  39.         y->succ = [=] { return next(y) == end() ? 0 : &*next(y); };
  40.         if (bad(y)) { erase(y); return; }
  41.         while (next(y) != end() && bad(next(y))) erase(next(y));
  42.         while (y != begin() && bad(prev(y))) erase(prev(y));
  43.     }
  44.  
  45.     ll eval(ll x) {
  46.         auto l = *lower_bound((line) { x, is_query });
  47.         return l.m * x + l.b;
  48.     }
  49. };
Add Comment
Please, Sign In to add comment