template <typename D> int Sign(D x) {
constexpr D EPS = std::is_integral<D>::value ? 0 : 1E-10;
/*
if (x > +EPS) return +1;
if (x < -EPS) return -1;
return 0;
*/
return (x > +EPS) - (x < -EPS);
}
template<typename D>
struct Vector {
D x{}, y{};
Vector() = default;
Vector(D x, D y) : x(x), y(y) {}
Vector operator-() const { return {-x, -y}; }
Vector operator*(D scalar) const { return {x * scalar, y * scalar}; }
Vector operator/(D scalar) const { return {x / scalar, y / scalar}; }
Vector operator+(const Vector& rhs) const { return {x + rhs.x, y + rhs.y}; }
Vector operator-(const Vector& rhs) const { return {x - rhs.x, y - rhs.y}; }
friend D dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
friend D crs(Vector a, Vector b) { return a.x * b.y - a.y * b.x; }
D sqd() const { return x * x + y * y; }
D len() const { return std::sqrt(sqd()); }
D ang() const { return std::atan2(y, x); }
Vector norm() const { return (*this) / len(); }
friend bool par(Vector a, Vector b) { return Sign(crs(a, b)) == 0; }
friend std::ostream& operator<<(std::ostream& os, const Vector& v) {
return os << '(' << v.x << ", " << v.y << ')';
}
};
template<typename D>
struct Segment {
D angle;
Vector<D> s, t;
Segment() = default;
Segment(Vector<D> s, Vector<D> t) : s(s), t(t) {}
D ang() { return angle = (t - s).ang(); }
int side(Vector<D> p) { return Sign(crs(p - s, t - s)); }
friend bool par(Segment a, Segment b) { return par(a.t - a.s, b.t - b.s); }
friend Vector<D> its(Segment a, Segment b) {
D k = crs(b.t - b.s, a.s - b.s) / crs(a.t - a.s, b.t - b.s);
return a.s + (a.t - a.s) * k;
}
friend std::ostream& operator<<(std::ostream& os, const Segment& p) {
return os << '{' << p.s << ", " << p.t << '}';
}
};
polygonal area
template<typename D>
D Area(const std::vector<Vector<D>>& p) {
D s = 0;
int n = (int) p.size();
for (int i = 0; i < n; i++)
s += crs(p[i], p[(i + 1) % n]);
return s / 2;
}
build convex hull
template<typename D>
std::vector<Vector<D>> ConvexHull(std::vector<Vector<D>> points) {
std::sort(points.begin(), points.end(), [&](auto a, auto b) {
return std::tie(a.x, a.y) < std::tie(b.x, b.y);
});
std::vector<Vector<D>> result;
for (int step = 0; step < 2; step++) {
int top = 0;
std::vector<Vector<D>> sta(points.size());
for (const auto& p : points) {
while (top > 1 && Sign(crs(sta[top - 2] - sta[top - 1],
sta[top - 2] - p)) < 1) top--;
sta[top++] = p;
}
for (int i = 0; i < top - 1; i++) result.emplace_back(sta[i]);
std::reverse(points.begin(), points.end());
}
return result;
}