Skip to content

Commit a76cab0

Browse files
committed
Optimize li_chao
1 parent 5de6fc3 commit a76cab0

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

li_chao.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// li_chao.cpp
2+
// Eric K. Zhang; Jul. 3, 2018
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
typedef long long LL;
8+
typedef pair<LL, LL> pll;
9+
inline LL f(pll a, int x) {
10+
return a.first * x + a.second;
11+
}
12+
13+
#define MAXLC 1000000
14+
#define INF (1LL<<60)
15+
pll line[MAXLC << 1];
16+
17+
void lc_init(int lo=0, int hi=MAXLC, int node=0) {
18+
if (lo > hi || line[node].second == INF)
19+
return;
20+
line[node] = { 0, INF };
21+
int mid = (lo + hi) / 2;
22+
lc_init(lo, mid - 1, 2 * node + 1);
23+
lc_init(mid + 1, hi, 2 * node + 2);
24+
}
25+
26+
void add_line(pll ln, int lo=0, int hi=MAXLC, int node=0) {
27+
int mid = (lo + hi) / 2;
28+
bool l = f(ln, lo) < f(line[node], lo);
29+
bool m = f(ln, mid) < f(line[node], mid);
30+
if (m) swap(line[node], ln);
31+
if (lo == hi || ln.second == INF)
32+
return;
33+
else if (l != m)
34+
add_line(ln, lo, mid - 1, 2 * node + 1);
35+
else
36+
add_line(ln, mid + 1, hi, 2 * node + 2);
37+
}
38+
39+
LL get(int x, int lo=0, int hi=MAXLC, int node=0) {
40+
int mid = (lo + hi) / 2;
41+
LL ret = f(line[node], x);
42+
if (x < mid)
43+
ret = min(ret, get(x, lo, mid - 1, 2 * node + 1));
44+
if (x > mid)
45+
ret = min(ret, get(x, mid + 1, hi, 2 * node + 2));
46+
return ret;
47+
}
48+
49+
int main() {
50+
lc_init();
51+
add_line({ 2, -1 }); // y = 2x - 1
52+
add_line({ -1, 9 }); // y = 9 - x
53+
54+
cout << get(0) << " = " << -1 << endl;
55+
cout << get(1) << " = " << 1 << endl;
56+
cout << get(3) << " = " << 5 << endl;
57+
cout << get(4) << " = " << 5 << endl;
58+
cout << get(5) << " = " << 4 << endl;
59+
cout << get(100) << " = " << -91 << endl;
60+
}

0 commit comments

Comments
 (0)