Guest User

Untitled

a guest
Apr 2nd, 2018
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.79 KB | None | 0 0
  1. // github.com/alxli/Algorithm-Anthology/blob/master/Section-1-Elementary-Algorithms/1.3.5%20Convex%20Hull%20Trick%20(Fully%20Dynamic).cpp
  2. // Fixed bugs in source
  3.  
  4. struct hull_optimizer {
  5.   struct line {
  6.     long long m, b, value;
  7.     double xlo;
  8.     bool is_query, query_max;
  9.  
  10.     line(long long m, long long b, long long v, bool is_query, bool query_max)
  11.         : m(m), b(b), value(v), xlo(-std::numeric_limits<double>::max()),
  12.           is_query(is_query), query_max(query_max) {}
  13.  
  14.     double intersect(const line &l) const {
  15.       if (m == l.m) {
  16.         return std::numeric_limits<double>::max();
  17.       }
  18.       return (double)(l.b - b)/(m - l.m);
  19.     }
  20.  
  21.     bool operator<(const line &l) const {
  22.       if (l.is_query) {
  23.         return query_max ? (xlo < l.value) : (l.value < xlo);
  24.       }
  25.       return m < l.m;
  26.     }
  27.   };
  28.  
  29.   std::set<line> hull;
  30.   bool query_max;
  31.  
  32.   typedef std::set<line>::iterator hulliter;
  33.  
  34.   bool has_prev(hulliter it) const {
  35.     return it != hull.begin();
  36.   }
  37.  
  38.   bool has_next(hulliter it) const {
  39.     return (it != hull.end()) && (++it != hull.end());
  40.   }
  41.  
  42.   bool irrelevant(hulliter it) const {
  43.     if (!has_prev(it) || !has_next(it)) {
  44.       return false;
  45.     }
  46.     hulliter prev = it, next = it;
  47.     --prev;
  48.     ++next;
  49.     return query_max ? (prev->intersect(*next) <= prev->intersect(*it))
  50.                      : (next->intersect(*prev) <= next->intersect(*it));
  51.   }
  52.  
  53.   hulliter update_left_border(hulliter it) {
  54.     if ((query_max && !has_prev(it)) || (!query_max && !has_next(it))) {
  55.       return it;
  56.     }
  57.     hulliter it2 = it;
  58.     double value = it->intersect(query_max ? *--it2 : *++it2);
  59.     line l(*it);
  60.     l.xlo = value;
  61.     hull.erase(it++);
  62.     return hull.insert(it, l);
  63.   }
  64.  
  65.   hull_optimizer(bool query_max = false) : query_max(query_max) {}
  66.  
  67.   void add_line(long long m, long long b) {
  68.     line l(m, b, 0, false, query_max);
  69.     hulliter it = hull.lower_bound(l);
  70.     if (it != hull.end() && it->m == l.m) {
  71.       if ((query_max && it->b < b) || (!query_max && b < it->b)) {
  72.         hull.erase(it++);
  73.       } else {
  74.         return;
  75.       }
  76.     }
  77.     it = hull.insert(it, l);
  78.     if (irrelevant(it)) {
  79.       hull.erase(it);
  80.       return;
  81.     }
  82.     auto it1 = it;
  83.     while (has_prev(it1) && irrelevant(--it1)) {
  84.       hull.erase(it1++);
  85.     }
  86.     it1 = it;
  87.     while (has_next(it1) && irrelevant(++it1)) {
  88.       hull.erase(it1--);
  89.     }
  90.     it1 = it = update_left_border(it);
  91.     if (has_prev(it1)) {
  92.       update_left_border(--it1);
  93.     }
  94.     if (has_next(it)) {
  95.       update_left_border(++it);
  96.     }
  97.   }
  98.  
  99.   long long query(long long x) const {
  100.     line q(0, 0, x, true, query_max);
  101.     hulliter it = hull.lower_bound(q);
  102.     if (query_max) {
  103.       --it;
  104.     }
  105.     return it->m*x + it->b;
  106.   }
  107. };
Add Comment
Please, Sign In to add comment