-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLiChaoTree.cpp
64 lines (59 loc) · 1.67 KB
/
LiChaoTree.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
63
64
// by luucasv
typedef long long T;
const T INF = 1e18, EPS = 1;
const int BUFFER_SIZE = 1e4;
struct Line {
T m, b;
Line(T m = 0, T b = INF): m(m), b(b){}
T apply(T x) { return x * m + b; }
};
struct Node {
Node *left, *right;
Line line;
Node(): left(NULL), right(NULL) {}
};
struct LiChaoTree {
Node *root, buffer[BUFFER_SIZE];
T min_value, max_value;
int buffer_pointer;
LiChaoTree(T min_value, T max_value): min_value(min_value), max_value(max_value + 1) { clear(); }
void clear() { buffer_pointer = 0; root = newNode(); }
void insert_line(T m, T b) { update(root, min_value, max_value, Line(m, b)); }
T eval(T x) { return query(root, min_value, max_value, x); }
void update(Node *cur, T l, T r, Line line) {
T m = l + (r - l) / 2;
bool left = line.apply(l) < cur->line.apply(l);
bool mid = line.apply(m) < cur->line.apply(m);
bool right = line.apply(r) < cur->line.apply(r);
if (mid) {
swap(cur->line, line);
}
if (r - l <= EPS) return;
if (left == right) return;
if (mid != left) {
if (cur->left == NULL) cur->left = newNode();
update(cur->left, l, m, line);
} else {
if (cur->right == NULL) cur->right = newNode();
update(cur->right, m, r, line);
}
}
T query(Node *cur, T l, T r, T x) {
if (cur == NULL) return INF;
if (r - l <= EPS) {
return cur->line.apply(x);
}
T m = l + (r - l) / 2;
T ans;
if (x < m) {
ans = query(cur->left, l, m, x);
} else {
ans = query(cur->right, m, r, x);
}
return min(ans, cur->line.apply(x));
}
Node* newNode() {
buffer[buffer_pointer] = Node();
return &buffer[buffer_pointer++];
}
};