Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
cht.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2#include"../../kyopro_library/algorithm/binary_search.hpp"
3
4/// @brief Convex Hull Trick
5/// @ref verify: https://judge.yosupo.jp/submission/291811
6/// @ref https://hcpc-hokudai.github.io/archive/algorithm_convex_hull_trick_001.pdf
7/// @tparam Min true のとき最小値を管理する
8template<typename T=ll, bool MIN=true>
9struct CHT {
10 CHT()=default;
11
12 /// @brief 直線 ax + b を追加する
13 /// @note O(log(N))
14 void add(T a, T b) {
15 if(!MIN) a*=-1, b*=-1;
16
17 if(lines.count(a) && lines[a]<=b) return;
18 lines[a]=b;
19 auto it=lines.find(a);
20 if(!need(it)) {
21 lines.erase(a);
22 return;
23 }
24 if(it!=lines.begin()) {
25 it=prev(it);
26 while(true) {
27 if(need(it)) break;
28 auto prv=prev(it);
29 lines.erase(it);
30 it=prv;
31 }
32 }
33 it=next(lines.find(a));
34 while (true) {
35 if(need(it)) break;
36 auto nxt=next(it);
37 lines.erase(it);
38 it=nxt;
39 }
40 }
41
42 /// @brief x に対する直線群の最小値を求める
43 /// @note O((log(N))^2)
44 T get(T x) {
45 auto [a,b]=*lines.lower_bound(BinarySearch<T>(lines.begin()->first,lines.rbegin()->first+1,[&](T m) {
46 auto it=lines.lower_bound(m);
47 if(it==lines.begin()) return true;
48 if(it==lines.end()) return false;
49 auto [a1,b1]=*prev(it);
50 auto [a2,b2]=*it;
51 return a1*x+b1>a2*x+b2;
52 }));
53 return (a*x+b)*(MIN?1:-1);
54 }
55
56private:
57 map<T,T> lines;
58 bool need(const typename map<T,T>::iterator it) {
59 if (it==lines.begin()||it==prev(lines.end())||it==lines.end()) return true;
60 auto prv=prev(it),nxt=next(it);
61 auto [a,b]=*it;
62 auto [a1,b1]=*nxt;
63 auto [a2,b2]=*prv;
64 return (lll)(a1-a)*(b-b2)<(lll)(a-a2)*(b1-b);
65 }
66};
Convex Hull Trick verify: https://judge.yosupo.jp/submission/291811 https://hcpc-hokudai....
Definition cht.hpp:9
void add(T a, T b)
直線 ax + b を追加する
Definition cht.hpp:14
T get(T x)
x に対する直線群の最小値を求める
Definition cht.hpp:44
CHT()=default