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 のとき最小値を管理する
8
template
<
typename
T=ll,
bool
MIN=
true
>
9
struct
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
56
private
:
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
};
CHT
Convex Hull Trick verify: https://judge.yosupo.jp/submission/291811 https://hcpc-hokudai....
Definition
cht.hpp:9
CHT::add
void add(T a, T b)
直線 ax + b を追加する
Definition
cht.hpp:14
CHT::get
T get(T x)
x に対する直線群の最小値を求める
Definition
cht.hpp:44
CHT::CHT
CHT()=default
algorithm
cht.hpp
構築:
1.13.2