summaryrefslogtreecommitdiff
path: root/content/datastructures/lichao.cpp
blob: 646ad683298450e3067ca9de8d9a7a1d8c8acdd4 (plain)
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
vector<ll> xs; // IMPORTANT: Initialize before constructing!
int findX(int i) {return lower_bound(all(xs), i) - begin(xs);}

struct Fun { // Default: Linear function. Change as needed. 
	ll m, c;
	ll operator()(int x) {return m*xs[x] + c;}
};

// Default: Computes min. Change lines with comment for max.
struct Lichao {
	static constexpr Fun id = {0, inf}; // {0, -inf}
	int n, cap;
	vector<Fun> seg;
	Lichao() : n(sz(xs)), cap(2 << __lg(n)), seg(2 * cap, id) {}
	
	void _insert(Fun f, int l, int r, int i) {
		while (i < 2 * cap) {
			int m = (l+r)/2;
			if (m >= n) {r = m; i = 2*i; continue;}
			Fun &g = seg[i];
			if (f(m) < g(m)) swap(f, g); // >
			if (f(l) < g(l)) r = m, i = 2*i; // >
			else l = m, i = 2*i+1;
	}}
	void insert(Fun f) {_insert(f, 0, cap, 1);}

	void _segmentInsert(Fun f, int l, int r, int a, int b, int i) {
		if (l <= a && b <= r) _insert(f, a, b, i);
		else if (a < r && l < b) {
			int m = (a+b)/2;
			_segmentInsert(f, l, r, a, m, 2*i);
			_segmentInsert(f, l, r, m, b, 2*i+1);
	}}
	void segmentInsert(Fun f, ll l, ll r) {
		_segmentInsert(f, findX(l), findX(r), 0, cap, 1);
	}

	ll _query(int x) {
		ll ans = inf; // -inf
		for (int i = x + cap; i > 0; i /= 2) {
			ans = min(ans, seg[i](x)); // max
		}
		return ans;
	}
	ll query(ll x) {return _query(findX(x));}
};