On this page
article
Li-Chao Tree
Sobre
Adiciona retas (ax+b), e computa o minimo entre as retas
em um dado ‘x’
Cuidado com overflow!
Se tiver overflow, tenta comprimir o ‘x’ ou usar
convex hull trick
O(log(MA-MI)), O(n) de memoria
Link original: lichao.cpp
Código
template<ll MI = ll(-1e9), ll MA = ll(1e9)> struct lichao {
struct line {
ll a, b;
array<int, 2> ch;
line(ll a_ = 0, ll b_ = LINF) :
a(a_), b(b_), ch({-1, -1}) {}
ll operator ()(ll x) { return a*x + b; }
};
vector<line> ln;
int ch(int p, int d) {
if (ln[p].ch[d] == -1) {
ln[p].ch[d] = ln.size();
ln.emplace_back();
}
return ln[p].ch[d];
}
lichao() { ln.emplace_back(); }
void add(line s, ll l=MI, ll r=MA, int p=0) {
ll m = (l+r)/2;
bool L = s(l) < ln[p](l);
bool M = s(m) < ln[p](m);
bool R = s(r) < ln[p](r);
if (M) swap(ln[p], s), swap(ln[p].ch, s.ch);
if (s.b == LINF) return;
if (L != M) add(s, l, m-1, ch(p, 0));
else if (R != M) add(s, m+1, r, ch(p, 1));
}
ll query(int x, ll l=MI, ll r=MA, int p=0) {
ll m = (l+r)/2, ret = ln[p](x);
if (ret == LINF) return ret;
if (x < m) return min(ret, query(x, l, m-1, ch(p, 0)));
return min(ret, query(x, m+1, r, ch(p, 1)));
}
};