This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/data_structure/convex_hull_trick.hpp"
をならし $O(1)$ で処理するデータ構造です.
ただし,追加される直線の $a$ は単調非増加である必要があります.
また,最小値クエリの $x$ は単調非減少である必要があります.
ConvecHullTrick<T> cht
空の直線群 cht
を構築します.
計算量
void cht.add(T a, T b)
cht
に直線 $y = ax + b$ を追加します.
制約
計算量
T cht(T x)
与えられた $x$ 座標における,直線群 cht
の $y$ 座標の最小値を取得します.
制約
計算量
#pragma once
#include "../template/template.hpp"
template <typename T>
struct ConvexHullTrick {
void add(const T& a, const T& b) {
Linear l(a, b);
assert(ls.empty() or ls.back().a >= l.a);
int len = (int)ls.size();
while(len >= 2 and check(ls[len - 2], ls[len - 1], l)) {
--len;
ls.pop_back();
}
ls.emplace_back(l);
}
T operator()(const T& x) {
assert(x >= x_last);
while((int)ls.size() >= 2 and ls[0](x) >= ls[1](x)) {
ls.pop_front();
}
x_last = x;
return ls[0](x);
}
private:
struct Linear {
T a, b;
Linear(const T& a = 0, const T& b = 0)
: a(a), b(b) {}
inline T operator()(const T& x) const {
return a * x + b;
}
};
inline bool check(const Linear& f1, const Linear& f2, const Linear& f3) const {
return (f2.a - f1.a) * (f3.b - f2.b) >= (f2.b - f1.b) * (f3.a - f2.a);
}
deque<Linear> ls;
T x_last = numeric_limits<T>::min();
};
#line 2 "src/template/template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<long long, long long>;
#define rep(i, a, b) for(long long i = (a); i < (b); ++i)
#define rrep(i, a, b) for(long long i = (a); i >= (b); --i)
constexpr long long inf = 4e18;
struct SetupIO {
SetupIO() {
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed << setprecision(30);
}
} setup_io;
#line 3 "src/data_structure/convex_hull_trick.hpp"
template <typename T>
struct ConvexHullTrick {
void add(const T& a, const T& b) {
Linear l(a, b);
assert(ls.empty() or ls.back().a >= l.a);
int len = (int)ls.size();
while(len >= 2 and check(ls[len - 2], ls[len - 1], l)) {
--len;
ls.pop_back();
}
ls.emplace_back(l);
}
T operator()(const T& x) {
assert(x >= x_last);
while((int)ls.size() >= 2 and ls[0](x) >= ls[1](x)) {
ls.pop_front();
}
x_last = x;
return ls[0](x);
}
private:
struct Linear {
T a, b;
Linear(const T& a = 0, const T& b = 0)
: a(a), b(b) {}
inline T operator()(const T& x) const {
return a * x + b;
}
};
inline bool check(const Linear& f1, const Linear& f2, const Linear& f3) const {
return (f2.a - f1.a) * (f3.b - f2.b) >= (f2.b - f1.b) * (f3.a - f2.a);
}
deque<Linear> ls;
T x_last = numeric_limits<T>::min();
};