Advertisement
radoslav11

Convex hull trick max

May 31st, 2016
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.66 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. #define endl '\n'
  3.  
  4. #define int long long
  5. #define double long double
  6.  
  7. using namespace std;
  8. const int MAXN = (1 << 20);
  9. const int inf = (int)1e17 + 42;
  10.  
  11. struct convex_hull_trick
  12. {
  13.     struct line
  14.     {
  15.         int m, b, is_query;
  16.         double line_x, val;
  17.  
  18.         line() {m = 0; b = 0; is_query = 0; line_x = 0; val = 0;}
  19.         line(int _m, int _b) {m = _m; b = _b; is_query = 0; line_x = 0; val = 0;}
  20.  
  21.         bool operator<(const line &l2) const
  22.         {
  23.             if(!is_query && !l2.is_query) return m < l2.m;
  24.             else if(l2.is_query) return line_x < l2.val;
  25.             else return val < l2.line_x;
  26.         }
  27.  
  28.         int value_at(int x) const
  29.         {
  30.             return m * x + b;
  31.         }
  32.     }; 
  33.  
  34.     set<line> hull;
  35.     void clear() { hull.clear(); }
  36.     void init() { clear(); }
  37.  
  38.     bool parallel(const line &l1, const line &l2) { return l1.m == l2.m; }
  39.  
  40.     double intersect_x(const line &l1, const line &l2)
  41.     {
  42.         if(parallel(l1, l2)) return inf;
  43.         return (double)(l1.b - l2.b) / (double)(l2.m - l1.m);
  44.     }
  45.  
  46.     bool has_prev(set<line>::iterator it) {return it != hull.end() && it != hull.begin();}
  47.     bool has_next(set<line>::iterator it) {return it != hull.end() && next(it) != hull.end();}
  48.  
  49.     bool irrelevant(const line &l1, const line &l2, const line &l3) { return intersect_x(l1, l3) <= intersect_x(l1, l2); }
  50.     bool irrelevant(set<line>::iterator it) { return has_prev(it) && has_next(it) && irrelevant(*prev(it), *it, *next(it)); }
  51.  
  52.     set<line>::iterator update_border(set<line>::iterator it)
  53.     {
  54.         double val;
  55.         if(!has_next(it)) val = inf;
  56.         else val = intersect_x(*it, *next(it));
  57.    
  58.         line tmp(*it);
  59.         tmp.line_x = val;
  60.         it = hull.erase(it);
  61.         it = hull.insert(it, tmp);
  62.         return it;
  63.     }
  64.  
  65.     void add_line(int m, int b)
  66.     {
  67.         line to_add = line(m, b);
  68.         set<line>::iterator it = hull.lower_bound(to_add);
  69.        
  70.         if(it != hull.end() && parallel(to_add, *it))
  71.         {
  72.             if(it->b < b) it = hull.erase(it);
  73.             else return;
  74.         }
  75.  
  76.         it = hull.insert(it, to_add);
  77.         if(irrelevant(it)) {it = hull.erase(it); return; }
  78.  
  79.         while(has_prev(it) && irrelevant(prev(it))) hull.erase(prev(it));
  80.         while(has_next(it) && irrelevant(next(it))) hull.erase(next(it));
  81.  
  82.         it = update_border(it);
  83.         if(has_prev(it)) update_border(prev(it));
  84.         if(has_next(it)) update_border(next(it));
  85.     }
  86.  
  87.     int query(int x)
  88.     {
  89.         line to_find;
  90.         to_find.is_query = 1;
  91.         to_find.val = x;
  92.  
  93.         set<line>::iterator best_line = hull.lower_bound(to_find);
  94.         if(best_line == hull.end())
  95.             return inf;
  96.        
  97.         return best_line->value_at(x);
  98.     }
  99. };
  100.  
  101. void read()
  102. {
  103.  
  104. }
  105.  
  106. convex_hull_trick cht;
  107.  
  108. void solve()
  109. {
  110.     cht.init();
  111. }
  112.  
  113. #undef int
  114. int main()
  115. {
  116.     ios_base::sync_with_stdio(false);
  117.     cin.tie(NULL);
  118.  
  119.     read();
  120.     solve();
  121.     return 0;
  122. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement