This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min"
#include <cstdio>
#include "src/data_structure/convex_hull_trick/Li_Chao_tree.hpp"
int main() {
using i64 = int64_t;
int n, q;
scanf("%d%d", &n, &q);
workspace::Li_Chao_tree<i64> cht(-1e9, 1e9);
while (n--) {
i64 l, r, a, b;
scanf("%lld%lld%lld%lld", &l, &r, &a, &b);
cht.insert(a, b, l, r);
}
while (q--) {
int t;
scanf("%d", &t);
if (t) {
int p;
scanf("%d", &p);
i64 ans = cht.eval(p);
if (ans == cht.infinity)
puts("INFINITY");
else
printf("%lld\n", ans);
} else {
i64 l, r, a, b;
scanf("%lld%lld%lld%lld", &l, &r, &a, &b);
cht.insert(a, b, l, r);
}
}
}
#line 1 "test/library-checker/segment_add_get_min.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min"
#include <cstdio>
#line 2 "src/data_structure/convex_hull_trick/Li_Chao_tree.hpp"
/**
* @file Li_Chao_tree.hpp
* @brief Li-Chao Tree
*/
#include <cassert>
#include <functional>
namespace workspace {
/**
* @brief Li-Chao Tree
*
* @tparam F Ordered Field.
* @tparam Comp Comparison function object type
* @tparam Infinity Identity element for 'Comp'.
* @tparam Eps Error tolerance
*/
template <class F, class Comp = std::less<F>,
F Infinity = std::numeric_limits<F>::max() / 2, F Eps = 1>
struct Li_Chao_tree {
constexpr static F infinity = Infinity;
constexpr static F eps = Eps;
struct line {
F slope = 0, intercept = Infinity;
F eval(F x) const { return slope * x + intercept; }
};
/**
* @param begin Lower bound of domain
* @param end Upper bound of domain
* @param comp Comparison function object
*/
Li_Chao_tree(const F begin, const F end, Comp comp = Comp())
: begin(begin), end(end), comp(comp) {}
~Li_Chao_tree() { delete root; }
bool empty() const { return !root; }
/**
* @brief Insert a line.
* @param ln Line
*/
void insert(line const &ln) { root = insert(root, begin, end, ln); }
/**
* @brief Insert a line.
* @param slope Slope
* @param intercept Intercept
*/
void insert(const F slope, const F intercept) {
insert(line{slope, intercept});
}
/**
* @brief Insert a segment.
* @param seg Segment
* @param __begin Left end, inclusive
* @param __end Right end, exclusive
*/
void insert(line const &seg, const F __begin, const F __end) {
if (__begin < __end) root = insert(root, begin, end, seg, __begin, __end);
}
/**
* @brief Insert a segment.
* @param slope Slope
* @param intercept Intercept
* @param __begin Left end, inclusive
* @param __end Right end, exclusive
*/
void insert(const F slope, const F intercept, const F __begin,
const F __end) {
insert(line{slope, intercept}, __begin, __end);
}
/**
* @param x Position
* @return The optimum at given position.
*/
F eval(const F x) const {
node *p = root;
F l = begin, r = end, opt = Infinity;
while (p) {
const F nval = p->__line.eval(x);
if (comp(nval, opt)) opt = nval;
if (r - l <= Eps) break;
const F mid = (l + r) / 2;
if (x < mid) {
p = p->__left;
r = mid;
} else {
p = p->__right;
l = mid;
}
}
return opt;
}
/**
* @param x Position
* @return The line achieving the optimum at given position.
*/
line get(const F x) const {
assert(!empty());
node *p = root, *arg = nullptr;
F l = begin, r = end, opt = Infinity;
while (p) {
const F nval = p->__line.eval(x);
if (comp(nval, opt)) opt = nval, arg = p;
if (r - l <= Eps) break;
const F mid = (l + r) / 2;
if (x < mid) {
p = p->__left;
r = mid;
} else {
p = p->__right;
l = mid;
}
}
return arg->__line;
}
protected:
struct node {
line __line;
node *__left = nullptr, *__right = nullptr;
node(line const &__l = line{}) : __line(__l) {}
node(node const &__x) : __line(__x.__line) {
if (__x.__left) __left = new node{*__x.__left};
if (__x.__right) __right = new node{*__x.__right};
}
node(node &&__x)
: __line(__x.__line), __left(__x.__left), __right(__x.__right) {
__x.__left = __x.__right = nullptr;
}
node &operator=(node const &__x) {
__line = __x.__line;
delete __left;
delete __right;
if (__x.__left) __left = new node{*__x.__left};
if (__x.__right) __right = new node{*__x.__right};
}
node &operator=(node &&__x) {
__line = __x.__line;
std::swap(__left, __x.__left);
std::swap(__right, __x.__right);
}
~node() {
delete __left;
delete __right;
}
};
F begin, end;
Comp comp;
node *root = nullptr;
public:
Li_Chao_tree(const Li_Chao_tree &__x)
: begin(__x.begin), end(__x.end), comp(__x.comp) {
if (__x.root) root = new node{*__x.root};
}
Li_Chao_tree(Li_Chao_tree &&__x)
: begin(__x.begin), end(__x.end), comp(__x.comp), root(__x.root) {
__x.root = nullptr;
}
Li_Chao_tree &operator=(const Li_Chao_tree &__x) {
begin = __x.begin;
end = __x.end;
comp = __x.comp;
if (__x.root) root = new node{*__x.root};
}
Li_Chao_tree &operator=(Li_Chao_tree &&__x) {
begin = __x.begin;
end = __x.end;
comp = __x.comp;
root = __x.root;
__x.root = nullptr;
}
protected:
node *insert(node *const p, const F l, const F r, line const &ln) {
if (!p) return new node{ln};
line &cur = p->__line;
const bool left_low = comp(ln.eval(l), cur.eval(l));
if (r - l <= Eps || left_low == comp(ln.eval(r), cur.eval(r))) {
if (left_low) cur = ln;
return p;
}
const F mid = (l + r) / 2;
if (comp(ln.eval(mid), cur.eval(mid))) {
if (left_low)
p->__right = insert(p->__right, mid, r, cur);
else
p->__left = insert(p->__left, l, mid, cur);
cur = ln;
} else {
if (left_low)
p->__left = insert(p->__left, l, mid, ln);
else
p->__right = insert(p->__right, mid, r, ln);
}
return p;
}
node *insert(node *p, const F l, const F r, line const &seg, const F s,
const F t) {
if (s < l + Eps && r < t + Eps) return insert(p, l, r, seg);
if (l < t && s < r) {
if (!p) p = new node{};
p->__left = insert(p->__left, l, (l + r) / 2, seg, s, t);
p->__right = insert(p->__right, (l + r) / 2, r, seg, s, t);
}
return p;
}
};
} // namespace workspace
#line 6 "test/library-checker/segment_add_get_min.test.cpp"
int main() {
using i64 = int64_t;
int n, q;
scanf("%d%d", &n, &q);
workspace::Li_Chao_tree<i64> cht(-1e9, 1e9);
while (n--) {
i64 l, r, a, b;
scanf("%lld%lld%lld%lld", &l, &r, &a, &b);
cht.insert(a, b, l, r);
}
while (q--) {
int t;
scanf("%d", &t);
if (t) {
int p;
scanf("%d", &p);
i64 ans = cht.eval(p);
if (ans == cht.infinity)
puts("INFINITY");
else
printf("%lld\n", ans);
} else {
i64 l, r, a, b;
scanf("%lld%lld%lld%lld", &l, &r, &a, &b);
cht.insert(a, b, l, r);
}
}
}