forked from amannntank/Competitive-Coding-Library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConvex Hull (Dynamic).cpp
105 lines (104 loc) · 2.53 KB
/
Convex Hull (Dynamic).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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//Original Code: https://www.codechef.com/viewsolution/8424830
struct cht{
struct Line{
lli a;
lli b;
lli val;
double xLeft;
bool type;
Line(lli _a = 0 , lli _b = 0){
a = _a;
b = _b;
xLeft = -INF;
type = 0;
val = 0;
}
lli valueAt(lli x) const{
return 1LL * a * x + b;
}
friend bool areParallel(const Line &l1, const Line &l2){
return l1.a == l2.a;
}
friend double intersectX(const Line &l1 , const Line &l2){
return areParallel(l1 , l2) ? INF : (l2.b - l1.b) / (double) (l1.a - l2.a);
}
bool operator < (const Line &l2) const{
if(!l2.type)
return a < l2.a;
return xLeft > l2.val;
}
};
set < Line > hull;
void init(){
hull.clear();
}
bool hasPrev(set < Line > :: iterator it){
return it != hull.begin();
}
bool hasNext(set < Line > :: iterator it){
return it != hull.end() && next(it) != hull.end();
}
bool irrelevant(const Line &l1 , const Line &l2 , const Line &l3){
return intersectX(l1,l3) <= intersectX(l1,l2);
}
bool irrelevant(set < Line > :: iterator it){
return hasPrev(it) && hasNext(it) && (irrelevant(*next(it) , *it , *prev(it)));
}
set < Line > :: iterator updateLeftBorder(set < Line > :: iterator it){
if(!hasNext(it)){
return it;
}
double val = intersectX(*it , *next(it));
Line buf(*it);
it = hull.erase(it);
buf.xLeft = val;
it = hull.insert(it, buf);
return it;
}
void addLine(lli a , lli b){
// dbg("add",a,b);
Line l3 = Line(a, b);
auto it = hull.lower_bound(l3);
if(it != hull.end() && areParallel(*it , l3)){
if(it -> b > b){
it = hull.erase(it);
}
else{
return;
}
}
it = hull.insert(it, l3);
if(irrelevant(it)){
hull.erase(it);
return;
}
while(hasPrev(it) && irrelevant(prev(it))){
hull.erase(prev(it));
}
while(hasNext(it) && irrelevant(next(it))){
hull.erase(next(it));
}
it = updateLeftBorder(it);
if(hasPrev(it)){
updateLeftBorder(prev(it));
}
if(hasNext(it)){
updateLeftBorder(next(it));
}
}
lli getBest(lli x){
// assert(!hull.empty());
if(hull.empty())
return INF;
Line q;
q.val = x;
q.type = 1;
auto bestLine = hull.lower_bound(q);
if(bestLine == hull.end()){
return INF;
}
return bestLine -> valueAt(x);
}
};
//Problem 1: http://codeforces.com/contest/320/problem/E
//Solution 1: http://codeforces.com/contest/320/submission/40481396