---
tags: codebook
---
# Li Chao segment tree
**problem:** [vjudge link](https://vjudge.net/problem/%E9%BB%91%E6%9A%97%E7%88%86%E7%82%B8-1568)
```cpp=
constexpr int maxn = 5e4 + 5;
struct line {
ld a, b;
ld operator()(ld x) {return a * x + b;}
} arr[(maxn + 1) << 2];
bool operator<(line a, line b) {return a.a < b.a;}
#define m ((l+r)>>1)
void insert(line x, int i = 1, int l = 0, int r = maxn) {
if (r - l == 1) {
if (x(l) > arr[i](l))
arr[i] = x;
return;
}
line a = max(arr[i], x), b = min(arr[i], x);
if (a(m) > b(m))
arr[i] = a, insert(b, i << 1, l, m);
else
arr[i] = b, insert(a, i << 1 | 1, m, r);
}
ld query(int x, int i = 1, int l = 0, int r = maxn) {
if (x < l || r <= x) return -numeric_limits<ld>::max();
if (r - l == 1) return arr[i](x);
return max({arr[i](x), query(x, i << 1, l, m), query(x, i << 1 | 1, m, r)});
}
#undef m
inline void solve() {
int n; cin >> n;
while (n--) {
string op; cin >> op;
if (op == "Project") {
ld s, p; cin >> s >> p;
insert(line{p, s - p});
} else {
int t; cin >> t;
cout << (ll)query(t) / 100 << endl;
// cout << query(t) << endl;
}
}
}
```
**problem:** [vjudge link](https://vjudge.net/problem/%E9%BB%91%E6%9A%97%E7%88%86%E7%82%B8-3165)
```cpp=
constexpr int maxn = 4e4 + 5;
// constexpr int maxn = 32;
struct line {
ld a, b; int id;
line(ld x = 0, ld y = 0, int i = 0): a(x), b(y), id(i) {}
ld operator()(ld x) {return a * x + b;}
} arr[(maxn + 1) << 2];
bool operator<(line a, line b) {return a.a < b.a;}
#define m ((l+r)>>1)
void insert(int ql, int qr, line x, int i = 1, int l = 0, int r = maxn) {
if (qr <= l || r <= ql) return;
if (l < ql || qr < r) {
insert(ql, qr, x, i << 1, l, m);
insert(ql, qr, x, i << 1 | 1, m, r);
return;
}
// debug(ql, qr, x.id, i, l, r);
if (r - l == 1) {
if (x(l) > arr[i](l))
arr[i] = x;
return;
}
line a = max(arr[i], x), b = min(arr[i], x);
if (a(m) > b(m) || (a(m) == b(m) && a.id < b.id))
arr[i] = a, insert(ql, qr, b, i << 1, l, m);
else
arr[i] = b, insert(ql, qr, a, i << 1 | 1, m, r);
}
P<ld, int> query(int x, int i = 1, int l = 0, int r = maxn) {
if (r - l == 1) return {arr[i](x), arr[i].id};
P<ld, int> tmp = (x < m ? query(x, i << 1, l, m) : query(x, i << 1 | 1, m, r));
if (arr[i](x) < tmp.first || (arr[i](x) == tmp.first && tmp.second < arr[i].id))
return tmp;
else
return {arr[i](x), arr[i].id};
}
#undef m
inline void solve() {
int n; cin >> n;
int lastans = 0, i = 0; ld a, b;
while (n--) {
int op, k, x0, y0, x1, y1;
switch (cin >> op, op) {
case 0:
cin >> k, k = (k + lastans - 1) % 39989 + 1;
cout << (lastans = query(k).second) << endl;
// debug(lastans = query(k).second);
break;
case 1:
cin >> x0 >> y0 >> x1 >> y1;
x0 = (x0 + lastans - 1) % 39989 + 1;
y0 = (y0 + lastans - 1) % 1000000000 + 1;
x1 = (x1 + lastans - 1) % 39989 + 1;
y1 = (y1 + lastans - 1) % 1000000000 + 1;
// y - y0 = ((y1 - y0) / (x1 - x0))(x - x0)
if (x1 - x0 == 0) {
a = 0, b = max(y0, y1);
insert(x0, x0 + 1, line(a, b, ++i));
break;
}
a = (ld)(y1 - y0) / (x1 - x0);
b = a * -x0 + y0;
if (x0 > x1) swap(x0, x1);
insert(x0, x1 + 1, line(a, b, ++i));
}
}
}
```