This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "ds/cht.hpp"
#pragma once
#include "arith/sqrt.hpp"
#include "la/vec.hpp"
#include "num/int/bisect.hpp"
template <class T>
using linear_fn = pair<T, T>;
template <class T>
T apply(linear_fn<T> f, T x) {
return f.first * x + f.second;
}
// checked (CF 660F)
// min/max of linear functions
template <class T, bool Maximize = false>
class convex_hull_trick {
public:
convex_hull_trick() : ready(true), hull({linear_fn<T>{0, sentinel()}}) {}
template <class It>
convex_hull_trick(It first, It last) {
init(first, last);
}
void clear() {
hull.clear(), edges.clear();
hull.emplace_back(0, sentinel());
}
template <bool Sorted = false, class It>
void init(It first, It last) {
clear();
int n = distance(first, last);
hull.reserve(n + 1), edges.reserve(n);
if (!Sorted) sort(first, last);
for (auto it = first; it != last; it++) {
while (!edges.empty() &&
(det(edges.back(), *it - hull.back()) <= 0) ^ Maximize)
hull.pop_back(), edges.pop_back();
edges.push_back(*it - hull.back()), hull.push_back(*it);
}
ready = true;
}
void rebuild() {
vector<linear_fn<T>> fs(all(hull));
fs.insert(fs.end(), all(aux));
sort(all(fs));
init(all(fs));
}
void add(linear_fn<T> f) { aux.push_back(f), ready = false; }
void add(T a, T b) { aux.emplace_back(a, b), ready = false; }
T apply(T x) {
assert(ready);
linear_fn<T> f(1, -x);
int i = bisect<int>(0, edges.size(), [&](int j) {
return (det(f, edges[j]) < 0) ^ Maximize;
});
T ans = ::apply(hull[i], x);
for (auto g : aux) ans = min(ans, ::apply(g, x));
return ans;
}
private:
bool ready;
vector<linear_fn<T>> hull, edges, aux;
static T sentinel() {
return floor_sqrt(numeric_limits<T>::max()) * (Maximize ? -1 : 1);
}
};
#line 2 "prelude.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vector<int>>;
using vll = vector<ll>;
using vvll = vector<vector<ll>>;
using vc = vector<char>;
#define rep2(i, m, n) for (auto i = (m); i < (n); i++)
#define rep(i, n) rep2(i, 0, n)
#define repr2(i, m, n) for (auto i = (n); i-- > (m);)
#define repr(i, n) repr2(i, 0, n)
#define all(x) begin(x), end(x)
auto ndvec(int n, auto e) { return vector(n, e); }
auto ndvec(int n, auto ...e) { return vector(n, ndvec(e...)); }
auto comp_key(auto&& f) { return [&](auto&& a, auto&& b) { return f(a) < f(b); }; }
auto& max(const auto& a, const auto& b) { return a < b ? b : a; }
auto& min(const auto& a, const auto& b) { return b < a ? b : a; }
#if __cpp_lib_ranges
namespace R = std::ranges;
namespace V = std::views;
#endif
#line 3 "arith/sqrt.hpp"
template <class T, enable_if_t<sizeof(T) <= 8>* = nullptr>
constexpr T floor_sqrt(T x) {
if (x == 0) return 0;
T s = round(sqrt(x));
return (s + x / s) / 2;
}
template <class T, enable_if_t<sizeof(T) <= 8>* = nullptr>
constexpr T ceil_sqrt(T x) {
return x == 0 ? 0 : floor_sqrt(x - 1) + 1;
}
#line 3 "la/vec.hpp"
template <class T, class U, class F, size_t... Is>
void zip_with_impl(T&& a, U&& b, F f, index_sequence<Is...>) {
(f(get<Is>(a), get<Is>(b)), ...);
}
template <class T, class U, class F>
void zip_with(T&& a, U&& b, F f) {
zip_with_impl(
forward<T>(a), forward<U>(b), f,
make_index_sequence<tuple_size_v<decay_t<T>>>{});
}
template <
class T, class U,
enable_if_t<tuple_size<T>::value == tuple_size<U>::value>* = nullptr>
T& operator+=(T& a, const U& b) {
zip_with(a, b, [](auto&& x, auto&& y) { x += y; });
return a;
}
template <
class T, class U,
enable_if_t<tuple_size<T>::value == tuple_size<U>::value>* = nullptr>
T& operator-=(T& a, const U& b) {
zip_with(a, b, [](auto&& x, auto&& y) { x -= y; });
return a;
}
template <class T, class U>
T& operator*=(T& a, U r) {
for_each(all(a), [=](auto& x) { x *= r; });
return a;
}
template <
class T, class U,
enable_if_t<tuple_size<T>::value == tuple_size<U>::value>* = nullptr>
T operator+(const T& a, const U& b) {
T c(a);
c += b;
return c;
}
template <
class T, class U,
enable_if_t<tuple_size<T>::value == tuple_size<U>::value>* = nullptr>
T operator-(const T& a, const U& b) {
T c(a);
c -= b;
return c;
}
template <class T, class U>
T operator*(U r, const T& a) {
T c(a);
c *= r;
return c;
}
template <class T, class E = tuple_element_t<0, T>>
E dot(const T& a, const T& b) {
E res(0);
zip_with(a, b, [&](auto&& x, auto&& y) { res += x * y; });
return res;
}
template <class T, enable_if_t<tuple_size_v<T> == 2>* = nullptr>
auto det(const T& a, const T& b) {
return get<0>(a) * get<1>(b) - get<1>(a) * get<0>(b);
}
// Returns k s.t. a == kb
// k=inf if b == 0
template <class T>
double factor(const T& a, const T& b) {
double res = numeric_limits<double>::infinity();
assert(dot(a, b) == 0);
zip_with(a, b, [&](auto&&x, auto&& y) {
if (y) res = x / y;
});
return res;
}
#line 2 "num/int/bisect.hpp"
template <class I, class F>
I bisect(I l, I r, F p) {
while (l != r) {
I m = ((l ^ r) >> 1) + (l & r);
if (p(m)) l = m + 1;
else r = m;
}
return l;
}
#line 5 "ds/cht.hpp"
template <class T>
using linear_fn = pair<T, T>;
template <class T>
T apply(linear_fn<T> f, T x) {
return f.first * x + f.second;
}
// checked (CF 660F)
// min/max of linear functions
template <class T, bool Maximize = false>
class convex_hull_trick {
public:
convex_hull_trick() : ready(true), hull({linear_fn<T>{0, sentinel()}}) {}
template <class It>
convex_hull_trick(It first, It last) {
init(first, last);
}
void clear() {
hull.clear(), edges.clear();
hull.emplace_back(0, sentinel());
}
template <bool Sorted = false, class It>
void init(It first, It last) {
clear();
int n = distance(first, last);
hull.reserve(n + 1), edges.reserve(n);
if (!Sorted) sort(first, last);
for (auto it = first; it != last; it++) {
while (!edges.empty() &&
(det(edges.back(), *it - hull.back()) <= 0) ^ Maximize)
hull.pop_back(), edges.pop_back();
edges.push_back(*it - hull.back()), hull.push_back(*it);
}
ready = true;
}
void rebuild() {
vector<linear_fn<T>> fs(all(hull));
fs.insert(fs.end(), all(aux));
sort(all(fs));
init(all(fs));
}
void add(linear_fn<T> f) { aux.push_back(f), ready = false; }
void add(T a, T b) { aux.emplace_back(a, b), ready = false; }
T apply(T x) {
assert(ready);
linear_fn<T> f(1, -x);
int i = bisect<int>(0, edges.size(), [&](int j) {
return (det(f, edges[j]) < 0) ^ Maximize;
});
T ans = ::apply(hull[i], x);
for (auto g : aux) ans = min(ans, ::apply(g, x));
return ans;
}
private:
bool ready;
vector<linear_fn<T>> hull, edges, aux;
static T sentinel() {
return floor_sqrt(numeric_limits<T>::max()) * (Maximize ? -1 : 1);
}
};