-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcht_add_monotone.hpp
67 lines (60 loc) · 1.89 KB
/
cht_add_monotone.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
template <typename T, bool isMax>
struct ConvexHullTrickAddMonotone {
struct Line {
T a, b;
constexpr Line(T _a, T _b) : a(_a), b(_b) {}
};
deque<Line> deq;
// l.a <= n.a <= m.a && l.a < m.a
static constexpr bool update(const Line &l, const Line &m, const Line &n) {
if (l.a == n.a) {
return l.b < n.b;
}
if (n.a == m.a) {
return m.b < n.b;
}
return (m.b - n.b) / (m.a - n.a) < (n.b - l.b) / (n.a - l.a);
}
template <typename U = T>
static constexpr U calc(const Line &line, U x) {
return line.a * x + line.b;
}
ConvexHullTrickAddMonotone() = default;
// add ax + b
void add(T a, T b) {
if constexpr (!isMax) a *= -1, b *= -1;
Line line(a, b);
if (deq.empty()) {
deq.push_back(line);
return;
}
if (line.a <= deq.front().a) {
if (line.a == deq.front().a) {
if (line.b <= deq.front().b) return;
deq.pop_front();
}
while (deq.size() >= 2 && !update(line, deq[1], deq.front())) deq.pop_front();
deq.push_front(line);
} else {
if (line.a == deq.back().a) {
if (line.b <= deq.back().b) return;
deq.pop_back();
}
while (deq.size() >= 2 && !update(deq.rbegin()[1], line, deq.back())) deq.pop_back();
deq.push_back(line);
}
}
template <typename U = T>
U query(U x) {
int l = 0, r = deq.size();
while (l + 1 < r) {
int m = (l + r) >> 1;
if (calc(deq[m], x) >= calc(deq[m - 1], x))
l = m;
else
r = m;
}
if constexpr (isMax) return calc(deq[l], x);
return -calc(deq[l], x);
}
};