forked from saketh-are/algo-lib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
line_container_monotonic.cpp
62 lines (48 loc) · 1.73 KB
/
line_container_monotonic.cpp
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
// {{{ data_structures/line }}}
#include <vector>
#include <cassert>
template<typename T>
struct line_container_monotonic : std::vector<line<T>> {
/* Inserts the line f(x) = a * x + b.
* a must be non-decreasing across calls.
*/
void insert_line(T a, T b) {
line<T> ins = { a, b };
if (!this->empty()) {
auto it = this->rbegin();
if (it->a > a)
assert(false);
if (it->a == a && it->b >= b)
return;
it->intersects_next = it->compute_intersection(ins);
while (this->size() >= 2 && next(it)->intersects_next >= it->intersects_next) {
this->pop_back();
it = next(it);
it->intersects_next = it->compute_intersection(ins);
}
}
this->push_back(ins);
}
/* Returns the maximum value at x among all inserted lines.
*/
T get_maximum(T x) const {
assert(!this->empty());
return std::lower_bound(this->begin(), this->end(), x, [](const line<T> &l, int _x) {
return l.intersects_next < _x;
})->evaluate(x);
}
/* Returns the maximum value at x among all inserted lines.
* Total runtime complexity is linear over sequential calls made
* with non-decreasing x if position is not modified externally.
*/
T get_maximum_monotonic(T x, size_t &position) const {
assert(!this->empty());
if (position > this->size())
position = this->size();
while (position > 0 && (*this)[position - 1].intersects_next >= x)
position--;
while (x > (*this)[position].intersects_next)
position++;
return (*this)[position].evaluate(x);
}
};