-
Notifications
You must be signed in to change notification settings - Fork 184
/
chtrick.cpp
40 lines (40 loc) · 1.46 KB
/
chtrick.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
// "Convex hull trick": data structure that maintains a set of lines y = mx + b and allows querying the minimum value of mx_0 + b over all lines for some given x_0. Very useful in optimizing DP algorithms for partitioning problems.
// Tested against USACO MAR08 acquire. TODO: Test against IOI '02 Batch.
struct ConvexHullTrick {
typedef long long LL;
vector<LL> M;
vector<LL> B;
vector<double> left;
ConvexHullTrick() {}
bool bad(LL m1, LL b1, LL m2, LL b2, LL m3, LL b3) {
// Careful, this may overflow
return (b3-b1)*(m1-m2) < (b2-b1)*(m1-m3);
}
// Add a new line to the structure, y = mx + b.
// Lines must be added in decreasing order of slope.
void add(LL m, LL b) {
while (M.size() >= 2 && bad(M[M.size()-2], B[B.size()-2], M.back(), B.back(), m, b)) {
M.pop_back(); B.pop_back(); left.pop_back();
}
if (M.size() && M.back() == m) {
if (B.back() > b) {
M.pop_back(); B.pop_back(); left.pop_back();
} else {
return;
}
}
if (M.size() == 0) {
left.push_back(-numeric_limits<double>::infinity());
} else {
left.push_back((double)(b - B.back())/(M.back() - m));
}
M.push_back(m);
B.push_back(b);
}
// Get the minimum value of mx + b among all lines in the structure.
// There must be at least one line.
LL query(LL x) {
int i = upper_bound(left.begin(), left.end(), x) - left.begin();
return M[i-1]*x + B[i-1];
}
};