-
Notifications
You must be signed in to change notification settings - Fork 697
/
Convex Hull (Dynamic).cpp
125 lines (109 loc) · 2.83 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//Original Code: https://ideone.com/fAjoZu
struct ConvexHullDynamic
{
static const int INF=1e18;
struct Line
{
int a, b; //y = ax + b
double xLeft; //Stores the intersection wiith previous line in the convex hull. First line has -INF
enum Type {line, maxQuery, minQuery} type;
int val;
explicit Line(int aa=0, int bb=0): a(aa), b(bb), xLeft(-INF), type(Type::line), val(0) {}
int valueAt(int x) const
{
return a*x + b;
}
friend bool isParallel(const Line &l1, const Line &l2)
{
return l1.a == l2.a;
}
friend double intersectX(const Line &l1, const Line &l2)
{
return isParallel(l1, l2)?INF:1.0*(l2.b-l1.b)/(l1.a-l2.a);
}
bool operator<(const Line& l2) const
{
if(l2.type == line)
return this->a < l2.a;
if(l2.type == maxQuery)
return this->xLeft < l2.val;
if(l2.type == minQuery)
return this->xLeft > l2.val;
}
};
bool isMax;
set<Line> hull;
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) && (
(isMax && irrelevant(*prev(it), *it, *next(it)))
|| (!isMax && irrelevant(*next(it), *it, *prev(it))));
}
//Updates xValue of line pointed by it
set<Line>::iterator updateLeftBorder(set<Line>::iterator it)
{
if(isMax && !hasPrev(it) || !isMax && !hasNext(it))
return it;
double val=intersectX(*it, isMax?(*prev(it)):(*next(it)));
Line temp(*it);
it=hull.erase(it);
temp.xLeft=val;
it=hull.insert(it, temp);
return it;
}
explicit ConvexHullDynamic(bool isMax): isMax(isMax) {}
void addLine(int a, int b) //Add ax + b in logN time
{
Line l3=Line(a, b);
auto it=hull.lower_bound(l3);
//If parallel liune is already in set, one of the lines becomes irrelevant
if(it!=hull.end() && isParallel(*it, l3))
{
if(isMax && it->b<b || !isMax && it->b>b)
it=hull.erase(it);
else
return;
}
it=hull.insert(it, l3);
if(irrelevant(it))
{
hull.erase(it);
return;
}
//Remove lines which became irrelevant after inserting
while(hasPrev(it) && irrelevant(prev(it)))
hull.erase(prev(it));
while(hasNext(it) && irrelevant(next(it)))
hull.erase(next(it));
//Update xLine
it=updateLeftBorder(it);
if(hasPrev(it))
updateLeftBorder(prev(it));
if(hasNext(it))
updateLeftBorder(next(it));
}
int getBest(int x)
{
Line q;
q.val=x;
q.type = isMax?Line::Type::maxQuery : Line::Type::minQuery;
auto bestLine=hull.lower_bound(q);
if(isMax)
--bestLine;
return bestLine->valueAt(x);
}
};
//Problem 1: http://codeforces.com/contest/320/problem/E
//Solution 1: http://codeforces.com/contest/320/submission/40481396