---
# System prepended metadata

title: Li Chao segment tree
tags: [codebook]

---

---
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));
		}
	}
}
```