Advertisement
osipyonok

ConvexHullDP

May 25th, 2017
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.97 KB | None | 0 0
  1. class ConvexHullDP{
  2.     typedef long long coef_t, coord_t, val_t;
  3. //Line 'y=a*x+b' represented by 2 coefficients 'a' and 'b'
  4. private:
  5.     struct Line{
  6.         coef_t a, b;
  7.         double xLeft;
  8.         enum Type {line, maxQuery, minQuery} type;
  9.         coord_t val;
  10.         explicit Line(coef_t aa=0, coef_t bb=0) : a(aa), b(bb), xLeft(-INFINITY), type(Type::line), val(0) {}
  11.         val_t valueAt(coord_t x) const { return a*x+b; }
  12.         friend bool areParallel(const Line& l1, const Line& l2) { return l1.a==l2.a; }
  13.         friend double intersectX(const Line& l1, const Line& l2) { return areParallel(l1,l2)?INFINITY:1.0*(l2.b-l1.b)/(l1.a-l2.a); }
  14.         bool operator<(const Line& l2) const{
  15.             if (l2.type == line) return this->a < l2.a;
  16.             if (l2.type == maxQuery) return this->xLeft < l2.val;
  17.             if (l2.type == minQuery) return this->xLeft > l2.val;
  18.             assert(0);
  19.             return false;
  20.         }
  21.     };
  22. private:
  23.     bool            isMax; //whether or not saved envelope is top(search of max value)
  24.     set<Line>  hull;  //envelope itself
  25. private:
  26.     bool hasPrev(set<Line>::iterator it) { return it!=hull.begin(); }
  27.     bool hasNext(set<Line>::iterator it) { return it!=hull.end() && next(it)!=hull.end(); }
  28.     bool irrelevant(const Line& l1, const Line& l2, const Line& l3) { return intersectX(l1,l3) <= intersectX(l1,l2); }
  29.     bool irrelevant(set<Line>::iterator it){
  30.         return hasPrev(it) && hasNext(it) && ((isMax && irrelevant(*prev(it), *it, *next(it)))
  31.                                               || (!isMax && irrelevant(*next(it), *it, *prev(it))));
  32.     }
  33.     set<Line>::iterator updateLeftBorder(set<Line>::iterator it){
  34.         if ((isMax && !hasPrev(it)) || (!isMax && !hasNext(it))) return it;
  35.         double val = intersectX(*it, isMax?*prev(it):*next(it));
  36.         Line buf(*it);
  37.         it = hull.erase(it), buf.xLeft = val, it = hull.insert(it, buf);
  38.         return it;
  39.     }
  40. public:
  41.     explicit ConvexHullDP(bool isMax): isMax(isMax) {} // true is for max and false is for min
  42.     void addLine(coef_t a, coef_t b){
  43.         Line l3 = Line(a, b);
  44.         auto it = hull.lower_bound(l3);
  45.         if (it!=hull.end() && areParallel(*it, l3)){
  46.             if ((isMax && it->b < b) || (!isMax && it->b > b)) it = hull.erase(it);
  47.             else return;
  48.         }
  49.         it = hull.insert(it, l3);
  50.         if (irrelevant(it)) { hull.erase(it); return; }
  51.         while (hasPrev(it) && irrelevant(prev(it))) hull.erase(prev(it));
  52.         while (hasNext(it) && irrelevant(next(it))) hull.erase(next(it));
  53.         it = updateLeftBorder(it);
  54.         if (hasPrev(it)) updateLeftBorder(prev(it));
  55.         if (hasNext(it)) updateLeftBorder(next(it));
  56.     }
  57.     val_t getBest(coord_t x) const{
  58.         Line q;
  59.         q.val = x, q.type = isMax ? Line::Type::maxQuery : Line::Type::minQuery;
  60.         auto bestLine = hull.lower_bound(q);
  61.         if (isMax) --bestLine;
  62.         return bestLine->valueAt(x);
  63.     }
  64. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement