This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min"
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#include "../../lib/99-operator/operator/ValueMin.cpp"
#include "../../lib/16-convex-hull-trick/LiChaoTree.cpp"
int main(void){
cin.tie(0);ios::sync_with_stdio(false);
int length,Q; cin >> length >> Q;
vector<long long> A(length),B(length),L(length),R(length),E(Q),F(Q),C(Q),D(Q),S(Q),TypeValue(Q);
for(int i = 0; i < length; ++i) {
cin >> L[i] >> R[i] >> A[i] >> B[i];
}
LiChaoTree<ValueMin<long long>> lct;
for(int i = 0; i < length; ++i) lct.x_push_back(L[i]),lct.x_push_back(R[i]);
for(int i = 0; i < Q; ++i) {
cin >> E[i];
if(E[i]) {
cin >> F[i];
lct.x_push_back(F[i]);
}
else {
cin >> S[i] >> TypeValue[i] >> C[i] >> D[i];
lct.x_push_back(S[i]);
lct.x_push_back(TypeValue[i]);
}
}
lct.build();
long long inf = 3e18;
for(int i = 0; i < length; ++i) lct.update({A[i],B[i]},L[i],R[i]);
for(int i = 0; i < Q; ++i) {
if(E[i]) {
long long ans = lct.get(F[i]);
if(ans!=inf) cout << ans << endl;
else cout << "INFINITY" << endl;
}
else {
lct.update({C[i],D[i]},S[i],TypeValue[i]);
}
}
}
#line 1 "test/convex-hull-trick/LiChaoTree-segment.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/segment_add_get_min"
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#line 1 "lib/99-operator/operator/ValueMin.cpp"
//最小値クエリ
template<class T> struct ValueMin {
using TypeValue = T;
inline static constexpr TypeValue unit_value = 3e18;
inline static constexpr bool func_compare(TypeValue l,TypeValue r){return l<r;}
};
#line 1 "lib/16-convex-hull-trick/LiChaoTree.cpp"
/*
* @title LiChaoTree
* @docs md/segment/convex-hull-trick/LiChaoTree.md
*/
template <typename Operator> class LiChaoTree{
using TypeValue = typename Operator::TypeValue;
using Line = pair<TypeValue,TypeValue>;
vector<TypeValue> x;
vector<Line> node;
vector<int> clz;
size_t length;
const size_t bit;
public:
LiChaoTree(const size_t bit=30):bit(bit){
//do nothing
}
inline void build(){
sort(x.begin(),x.end());
x.erase(unique(x.begin(),x.end()),x.end());
TypeValue maxi = x.back() + 1;
for (length = 1; length < x.size(); length *= 2);
x.resize(length, maxi);
node.resize(2*length,make_pair(0,Operator::unit_value));
clz.resize(2*length,32);
for(size_t i = 1; i < 2*length; ++i) {
// for(int j = 0; j < bit; ++j) if(i&(1<<j)) clz[i] = 31-j;
clz[i] = __builtin_clz(i);
}
}
void x_push_back(TypeValue argx){
x.push_back(argx);
}
//return y = ax+b
inline static constexpr TypeValue f(Line& line,TypeValue& t) {
return line.first*t + line.second;
}
inline void update(Line line,int i = 1){
while(i < 2*length){
int l = (i<<(clz[i]-clz[length]))-length;
int r = l + (length>>(31-clz[i])) - 1;
int m = (l+r)>>1;
bool flgl = Operator::func_compare(f(line,x[l]),f(node[i],x[l]));
bool flgm = Operator::func_compare(f(line,x[m]),f(node[i],x[m]));
bool flgr = Operator::func_compare(f(line,x[r]),f(node[i],x[r]));
if(flgl&&flgr) node[i] = line;
if(flgl==flgr) break;
if(flgm) swap(node[i],line),swap(flgl,flgr);
i = (i<<1)+flgr;
}
}
inline void update(Line line,TypeValue l,TypeValue r){
l = distance(x.begin(),lower_bound(x.begin(),x.end(),l))+length;
r = distance(x.begin(),lower_bound(x.begin(),x.end(),r))+length;
for(; l < r; l >>=1, r >>=1) {
if(l&1) update(line,l),l++;
if(r&1) --r,update(line,r);
}
}
inline TypeValue get(TypeValue t){
int i = distance(x.begin(),lower_bound(x.begin(),x.end(),t))+length;
TypeValue res = Operator::unit_value;
for(;1<=i;i>>=1) if(!Operator::func_compare(res,f(node[i],t))) res = f(node[i],t);
return res;
}
};
#line 9 "test/convex-hull-trick/LiChaoTree-segment.test.cpp"
int main(void){
cin.tie(0);ios::sync_with_stdio(false);
int length,Q; cin >> length >> Q;
vector<long long> A(length),B(length),L(length),R(length),E(Q),F(Q),C(Q),D(Q),S(Q),TypeValue(Q);
for(int i = 0; i < length; ++i) {
cin >> L[i] >> R[i] >> A[i] >> B[i];
}
LiChaoTree<ValueMin<long long>> lct;
for(int i = 0; i < length; ++i) lct.x_push_back(L[i]),lct.x_push_back(R[i]);
for(int i = 0; i < Q; ++i) {
cin >> E[i];
if(E[i]) {
cin >> F[i];
lct.x_push_back(F[i]);
}
else {
cin >> S[i] >> TypeValue[i] >> C[i] >> D[i];
lct.x_push_back(S[i]);
lct.x_push_back(TypeValue[i]);
}
}
lct.build();
long long inf = 3e18;
for(int i = 0; i < length; ++i) lct.update({A[i],B[i]},L[i],R[i]);
for(int i = 0; i < Q; ++i) {
if(E[i]) {
long long ans = lct.get(F[i]);
if(ans!=inf) cout << ans << endl;
else cout << "INFINITY" << endl;
}
else {
lct.update({C[i],D[i]},S[i],TypeValue[i]);
}
}
}