結果
問題 | No.199 星を描こう |
ユーザー | yuruhiya |
提出日時 | 2020-11-02 16:59:11 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 48,222 bytes |
コンパイル時間 | 2,708 ms |
コンパイル使用メモリ | 231,116 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-07-22 06:22:40 |
合計ジャッジ時間 | 3,754 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 2 ms
5,376 KB |
testcase_14 | AC | 2 ms
5,376 KB |
testcase_15 | AC | 2 ms
5,376 KB |
testcase_16 | AC | 2 ms
5,376 KB |
testcase_17 | AC | 2 ms
5,376 KB |
testcase_18 | AC | 2 ms
5,376 KB |
testcase_19 | AC | 2 ms
5,376 KB |
testcase_20 | AC | 2 ms
5,376 KB |
testcase_21 | AC | 2 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 2 ms
5,376 KB |
testcase_24 | AC | 2 ms
5,376 KB |
testcase_25 | AC | 2 ms
5,376 KB |
testcase_26 | AC | 2 ms
5,376 KB |
testcase_27 | AC | 2 ms
5,376 KB |
ソースコード
#line 2 "/home/yuruhiya/programming/library/template/template.cpp" #include <bits/stdc++.h> #line 6 "/home/yuruhiya/programming/library/template/constants.cpp" using namespace std; #define rep(i, n) for (int i = 0; i < (n); ++i) #define FOR(i, m, n) for (int i = (m); i < (n); ++i) #define rrep(i, n) for (int i = (n)-1; i >= 0; --i) #define rfor(i, m, n) for (int i = (m); i >= (n); --i) #define unless(c) if (!(c)) #define sz(x) ((int)(x).size()) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r) using namespace std; using ll = long long; using LD = long double; using VB = vector<bool>; using VVB = vector<VB>; using VI = vector<int>; using VVI = vector<VI>; using VL = vector<ll>; using VVL = vector<VL>; using VS = vector<string>; using VD = vector<LD>; using PII = pair<int, int>; using VP = vector<PII>; using PLL = pair<ll, ll>; using VPL = vector<PLL>; template <class T> using PQ = priority_queue<T>; template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>; constexpr int inf = 1e9; constexpr long long inf_ll = 1e18, MOD = 1000000007; constexpr long double PI = 3.14159265358979323846, EPS = 1e-12; #line 7 "/home/yuruhiya/programming/library/template/Input.cpp" using namespace std; #ifdef _WIN32 #define getchar_unlocked _getchar_nolock #define putchar_unlocked _putchar_nolock #define fwrite_unlocked fwrite #define fflush_unlocked fflush #endif class Input { static int gc() { return getchar_unlocked(); } template <class T> static void i(T& v) { cin >> v; } static void i(char& v) { while (isspace(v = gc())) ; } static void i(bool& v) { v = in<char>() != '0'; } static void i(string& v) { v.clear(); char c; for (i(c); !isspace(c); c = gc()) v += c; } static void i(int& v) { bool neg = false; v = 0; char c; i(c); if (c == '-') { neg = true; c = gc(); } for (; isdigit(c); c = gc()) v = v * 10 + (c - '0'); if (neg) v = -v; } static void i(long long& v) { bool neg = false; v = 0; char c; i(c); if (c == '-') { neg = true; c = gc(); } for (; isdigit(c); c = gc()) v = v * 10 + (c - '0'); if (neg) v = -v; } static void i(double& v) { double dp = 1; bool neg = false, adp = false; v = 0; char c; i(c); if (c == '-') { neg = true; c = gc(); } for (; isdigit(c) || c == '.'; c = gc()) { if (c == '.') adp = true; else if (adp) v += (c - '0') * (dp *= 0.1); else v = v * 10 + (c - '0'); } if (neg) v = -v; } static void i(long double& v) { long double dp = 1; bool neg = false, adp = false; v = 0; char c; i(c); if (c == '-') { neg = true; c = gc(); } for (; isdigit(c) || c == '.'; c = gc()) { if (c == '.') adp = true; else if (adp) v += (c - '0') * (dp *= 0.1); else v = v * 10 + (c - '0'); } if (neg) v = -v; } template <class T, class U> static void i(pair<T, U>& v) { i(v.first); i(v.second); } template <class T> static void i(vector<T>& v) { for (auto& e : v) i(e); } template <size_t N = 0, class T> static void input_tuple(T& v) { if constexpr (N < tuple_size_v<T>) { i(get<N>(v)); input_tuple<N + 1>(v); } } template <class... T> static void i(tuple<T...>& v) { input_tuple(v); } struct InputV { int n, m; InputV(int _n) : n(_n), m(0) {} InputV(const pair<int, int>& nm) : n(nm.first), m(nm.second) {} template <class T> operator vector<T>() { vector<T> v(n); i(v); return v; } template <class T> operator vector<vector<T>>() { vector<vector<T>> v(n, vector<T>(m)); i(v); return v; } }; public: static string read_line() { string v; char c; for (i(c); c != '\n' && c != '\0'; c = gc()) v += c; return v; } template <class T> static T in() { T v; i(v); return v; } template <class T> operator T() const { return in<T>(); } int operator--(int) const { return in<int>() - 1; } InputV operator[](int n) const { return InputV(n); } InputV operator[](const pair<int, int>& n) const { return InputV(n); } void operator()() const {} template <class H, class... T> void operator()(H&& h, T&&... t) const { i(h); operator()(forward<T>(t)...); } private: template <template <class...> class, class...> struct Multiple; template <template <class...> class V, class Head, class... Tail> struct Multiple<V, Head, Tail...> { template <class... Args> using vec = V<vector<Head>, Args...>; using type = typename Multiple<vec, Tail...>::type; }; template <template <class...> class V> struct Multiple<V> { using type = V<>; }; template <class... T> using multiple_t = typename Multiple<tuple, T...>::type; template <size_t N = 0, class T> void in_multiple(T& t) const { if constexpr (N < tuple_size_v<T>) { auto& vec = get<N>(t); using V = typename remove_reference_t<decltype(vec)>::value_type; vec.push_back(in<V>()); in_multiple<N + 1>(t); } } public: template <class... T> auto multiple(int H) const { multiple_t<T...> res; while (H--) in_multiple(res); return res; } } in; #define input(T) Input::in<T>() #define INT input(int) #define LL input(long long) #define STR input(string) #define inputs(T, ...) \ T __VA_ARGS__; \ in(__VA_ARGS__) #define ini(...) inputs(int, __VA_ARGS__) #define inl(...) inputs(long long, __VA_ARGS__) #define ins(...) inputs(string, __VA_ARGS__) #line 6 "/home/yuruhiya/programming/library/template/Output.cpp" #include <charconv> #line 9 "/home/yuruhiya/programming/library/template/Output.cpp" using namespace std; struct BoolStr { const char *t, *f; BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {} } Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0"); struct DivStr { const char *d, *l; DivStr(const char* _d, const char* _l) : d(_d), l(_l) {} } spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"), no_endl(" ", ""); class Output { BoolStr B{Yes}; DivStr D{spc}; void p(int v) const { char buf[12]{}; if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) { fwrite(buf, sizeof(char), ptr - buf, stdout); } else { assert(false); } } void p(long long v) const { char buf[21]{}; if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) { fwrite(buf, sizeof(char), ptr - buf, stdout); } else { assert(false); } } void p(bool v) const { p(v ? B.t : B.f); } void p(char v) const { putchar_unlocked(v); } void p(const char* v) const { fwrite_unlocked(v, 1, strlen(v), stdout); } void p(double v) const { printf("%.20f", v); } void p(long double v) const { printf("%.20Lf", v); } template <class T> void p(const T& v) const { cout << v; } template <class T, class U> void p(const pair<T, U>& v) const { p(v.first); p(D.d); p(v.second); } template <class T> void p(const vector<T>& v) const { rep(i, sz(v)) { if (i) p(D.d); p(v[i]); } } template <class T> void p(const vector<vector<T>>& v) const { rep(i, sz(v)) { if (i) p(D.l); p(v[i]); } } public: Output& operator()() { p(D.l); return *this; } template <class H> Output& operator()(H&& h) { p(h); p(D.l); return *this; } template <class H, class... T> Output& operator()(H&& h, T&&... t) { p(h); p(D.d); return operator()(forward<T>(t)...); } template <class It> Output& range(const It& l, const It& r) { for (It i = l; i != r; i++) { if (i != l) p(D.d); p(*i); } p(D.l); return *this; } template <class T> Output& range(const T& a) { range(a.begin(), a.end()); return *this; } template <class... T> void exit(T&&... t) { operator()(forward<T>(t)...); std::exit(EXIT_SUCCESS); } Output& flush() { fflush_unlocked(stdout); return *this; } Output& set(const BoolStr& b) { B = b; return *this; } Output& set(const DivStr& d) { D = d; return *this; } Output& set(const char* t, const char* f) { B = BoolStr(t, f); return *this; } } out; #line 3 "/home/yuruhiya/programming/library/template/Step.cpp" using namespace std; template <class T> struct Step { class It { T a, b, c; public: constexpr It() : a(T()), b(T()), c(T()) {} constexpr It(T _b, T _c, T _s) : a(_b), b(_c), c(_s) {} constexpr It& operator++() { --b; a += c; return *this; } constexpr It operator++(int) { It tmp = *this; --b; a += c; return tmp; } constexpr const T& operator*() const { return a; } constexpr const T* operator->() const { return &a; } constexpr bool operator==(const It& i) const { return b == i.b; } constexpr bool operator!=(const It& i) const { return !(b == i.b); } constexpr T start() const { return a; } constexpr T size() const { return b; } constexpr T step() const { return c; } }; constexpr Step(T b, T c, T s) : be(b, c, s) {} constexpr It begin() const { return be; } constexpr It end() const { return en; } constexpr T start() const { return be.start(); } constexpr T size() const { return be.size(); } constexpr T step() const { return be.step(); } constexpr T sum() const { return start() * size() + step() * (size() * (size() - 1) / 2); } operator vector<T>() const { return to_a(); } auto to_a() const { vector<T> res; res.reserve(size()); for (auto i : *this) { res.push_back(i); } return res; } using value_type = T; using iterator = It; private: It be, en; }; template <class T> inline constexpr auto step(T a) { return Step<T>(0, a, 1); } template <class T> inline constexpr auto step(T a, T b) { return Step<T>(a, b - a, 1); } template <class T> inline constexpr auto step(T a, T b, T c) { return Step<T>(a, a < b ? (b - a - 1) / c + 1 : 0, c); } #line 8 "/home/yuruhiya/programming/library/template/Ruby.cpp" using namespace std; template <class F> struct Callable { F func; Callable(const F& f) : func(f) {} }; template <class T, class F> auto operator|(const T& v, const Callable<F>& c) { return c.func(v); } struct Sort_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { sort(begin(v), end(v), f); return v; }); } template <class T> friend auto operator|(T v, [[maybe_unused]] const Sort_impl& c) { sort(begin(v), end(v)); return v; } } Sort; struct SortBy_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { sort(begin(v), end(v), [&](const auto& i, const auto& j) { return f(i) < f(j); }); return v; }); } } SortBy; struct RSort_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { sort(rbegin(v), rend(v), f); return v; }); } template <class T> friend auto operator|(T v, [[maybe_unused]] const RSort_impl& c) { sort(rbegin(v), rend(v)); return v; } } RSort; struct RSortBy_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { sort(begin(v), end(v), [&](const auto& i, const auto& j) { return f(i) > f(j); }); return v; }); } } RSortBy; struct Reverse_impl { template <class T> friend auto operator|(T v, const Reverse_impl& c) { reverse(begin(v), end(v)); return v; } } Reverse; struct Unique_impl { template <class T> friend auto operator|(T v, const Unique_impl& c) { v.erase(unique(begin(v), end(v), end(v))); return v; } } Unique; struct Uniq_impl { template <class T> friend auto operator|(T v, const Uniq_impl& c) { sort(begin(v), end(v)); v.erase(unique(begin(v), end(v)), end(v)); return v; } } Uniq; struct Rotate_impl { auto operator()(int&& left) { return Callable([&](auto v) { int s = static_cast<int>(size(v)); assert(-s <= left && left <= s); if (0 <= left) { rotate(begin(v), begin(v) + left, end(v)); } else { rotate(begin(v), end(v) + left, end(v)); } return v; }); } } Rotate; struct Max_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { return *max_element(begin(v), end(v), f); }); } template <class T> friend auto operator|(T v, const Max_impl& c) { return *max_element(begin(v), end(v)); } } Max; struct Min_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { return *min_element(begin(v), end(v), f); }); } template <class T> friend auto operator|(T v, const Min_impl& c) { return *min_element(begin(v), end(v)); } } Min; struct MaxPos_impl { template <class T> friend auto operator|(T v, const MaxPos_impl& c) { return max_element(begin(v), end(v)) - begin(v); } } MaxPos; struct MinPos_impl { template <class T> friend auto operator|(T v, const MinPos_impl& c) { return min_element(begin(v), end(v)) - begin(v); } } MinPos; struct MaxBy_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { auto max_it = begin(v); auto max_val = f(*max_it); for (auto it = next(begin(v)); it != end(v); ++it) { if (auto val = f(*it); max_val < val) { max_it = it; max_val = val; } } return *max_it; }); } } MaxBy; struct MinBy_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { auto min_it = begin(v); auto min_val = f(*min_it); for (auto it = next(begin(v)); it != end(v); ++it) { if (auto val = f(*it); min_val > val) { min_it = it; min_val = val; } } return *min_it; }); } } MinBy; struct MaxOf_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { auto max_val = f(*begin(v)); for (auto it = next(begin(v)); it != end(v); ++it) { if (auto val = f(*it); max_val < val) { max_val = val; } } return max_val; }); } } MaxOf; struct MinOf_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { auto min_val = f(*begin(v)); for (auto it = next(begin(v)); it != end(v); ++it) { if (auto val = f(*it); min_val > val) { min_val = val; } } return min_val; }); } } MinOf; struct Count_impl { template <class V> auto operator()(const V& val) { return Callable([&](auto v) { return count(begin(v), end(v), val); }); } } Count; struct CountIf_impl { template <class F> auto operator()(const F& f) { return Callable([&](auto v) { return count_if(begin(v), end(v), f); }); } } CountIf; struct Index_impl { template <class V> auto operator()(const V& val) { return Callable([&](auto v) -> optional<int> { auto res = find(begin(v), end(v), val); return res != end(v) ? optional(res - begin(v)) : nullopt; }); } } Index; struct IndexIf_impl { template <class F> auto operator()(const F& f) { return Callable([&](auto v) -> optional<int> { auto res = find_if(begin(v), end(v), f); return res != end(v) ? optional(res - begin(v)) : nullopt; }); } } IndexIf; struct FindIf_impl { template <class F> auto operator()(const F& f) { return Callable([&](auto v) -> optional<typename decltype(v)::value_type> { auto res = find_if(begin(v), end(v), f); return res != end(v) ? optional(*res) : nullopt; }); } } FindIf; struct Sum_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { return accumulate(next(begin(v)), end(v), f(*begin(v)), [&](const auto& a, const auto& b) { return a + f(b); }); }); } template <class T> friend auto operator|(T v, const Sum_impl& c) { return accumulate(begin(v), end(v), typename T::value_type{}); } } Sum; struct Includes { template <class V> auto operator()(const V& val) { return Callable([&](auto v) { return find(begin(v), end(v), val) != end(v); }); } } Includes; struct IncludesIf_impl { template <class F> auto operator()(const F& f) { return Callable([&](auto v) { return find_if(begin(v), end(v), f) != end(v); }); } } IncludesIf; struct RemoveIf_impl { template <class F> auto operator()(const F& f) { return Callable([&](auto v) { v.erase(remove_if(begin(v), end(v), f), end(v)); return v; }); } } RemoveIf; struct Each_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { for (const auto& i : v) { f(i); } }); } } Each; struct Select_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { using value_type = typename decltype(v)::value_type; vector<value_type> res; for (const auto& i : v) { if (f(i)) res.push_back(i); } return res; }); } } Select; struct Map_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { using result_type = invoke_result_t<F, typename decltype(v)::value_type>; vector<result_type> res; res.reserve(size(v)); for (const auto& i : v) { res.push_back(f(i)); } return res; }); } } Map; struct Indexed_impl { template <class T> friend auto operator|(const T& v, Indexed_impl& c) { using value_type = typename T::value_type; vector<pair<value_type, int>> res; res.reserve(size(v)); int index = 0; for (const auto& i : v) { res.emplace_back(i, index++); } return res; } } Indexed; struct AllOf_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { for (const auto& i : v) { if (!f(i)) return false; } return true; }); } } AllOf; struct AnyOf_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { for (const auto& i : v) { if (f(i)) return true; } return false; }); } } AnyOf; struct NoneOf_impl { template <class F> auto operator()(F&& f) { return Callable([&](auto v) { for (const auto& i : v) { if (f(i)) return false; } return true; }); } } NoneOf; struct Tally_impl { template <class F> auto operator()(size_t max_val) { return Callable([&](auto v) { vector<size_t> res(max_val); for (const auto& i : v) { res[static_cast<size_t>(i)]++; } return res; }); } template <class T, class value_type = typename T::value_type> friend auto operator|(const T& v, Tally_impl& c) { map<value_type, size_t> res; for (const auto& i : v) { res[i]++; } return res; } } Tally; template <class T> auto operator*(const vector<T>& a, size_t n) { T res; for (size_t i = 0; i < n; ++i) { res.insert(res.end(), a.begin(), a.end()); } return res; } auto operator*(string a, size_t n) { string res; for (size_t i = 0; i < n; ++i) { res += a; } return res; } template <class T, class U> auto& operator<<(vector<T>& a, const U& b) { a.insert(a.end(), all(b)); return a; } template <class T> auto& operator<<(string& a, const T& b) { a.insert(a.end(), all(b)); return a; } template <class T, class U> auto operator+(vector<T> a, const U& b) { a << b; return a; } template <class T> auto operator+(string a, const T& b) { a << b; return a; } #line 6 "/home/yuruhiya/programming/library/template/functions.cpp" using namespace std; template <class T, class U> inline int Lower(const T& a, const U& v) { return lower_bound(all(a), v) - a.begin(); } template <class T, class U> inline int Upper(const T& a, const U& v) { return upper_bound(all(a), v) - a.begin(); } template <class T> inline auto Slice(const T& v, size_t i, size_t len) { return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T(); } template <class T> inline T Ceil(T n, T m) { return (n + m - 1) / m; } template <class T> inline T Ceil2(T n, T m) { return Ceil(n, m) * m; } template <class T> inline T Tri(T n) { return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1); } template <class T> inline T nC2(T n) { return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1); } template <class T> inline T Mid(const T& l, const T& r) { return l + (r - l) / 2; } template <class T> inline bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } return false; } template <class T> inline bool chmin(T& a, const T& b) { if (a > b) { a = b; return true; } return false; } template <class T> inline bool inRange(const T& v, const T& min, const T& max) { return min <= v && v < max; } template <class T> inline bool isSquere(T n) { T s = sqrt(n); return s * s == n || (s + 1) * (s + 1) == n; } template <class T = long long> inline T BIT(int b) { return T(1) << b; } template <class T, class U = typename T::value_type> inline U Gcdv(const T& v) { return accumulate(next(v.begin()), v.end(), U(*v.begin()), gcd<U, U>); } template <class T, class U = typename T::value_type> inline U Lcmv(const T& v) { return accumulate(next(v.begin()), v.end(), U(*v.begin()), lcm<U, U>); } template <class T> inline T Pow(T a, T n) { T r = 1; while (n > 0) { if (n & 1) r *= a; a *= a; n /= 2; } return r; } template <class T> inline T Powmod(T a, T n, T m = MOD) { T r = 1; while (n > 0) { if (n & 1) r = r * a % m, n--; else a = a * a % m, n /= 2; } return r; } #line 9 "/home/yuruhiya/programming/library/template/template.cpp" #if __has_include(<library/dump.hpp>) #include <library/dump.hpp> #define LOCAL #else #define dump(...) ((void)0) #endif template <class T> constexpr T oj_local(const T& oj, const T& local) { #ifndef LOCAL return oj; #else return local; #endif } #line 5 "/home/yuruhiya/programming/library/Geometry/Geometric.hpp" #include <optional> using namespace std; namespace Geometric { using LD = long double; constexpr long double PI = 3.14159265358979323846, EPS = 1e-12; constexpr bool Equal(LD a, LD b); // a > 0 : +1 // a = 0 : 0 // a < 0 : -1 constexpr int sgn(LD a); constexpr LD deg_to_rad(LD deg); constexpr LD rad_to_deg(LD rad); struct Vec2; struct Line; struct Segment; struct Rect; struct Circle; struct Polygon; // AB から見て BC が左に曲がる : +1 // AB から見て BC が右に曲がる : -1 // ABC, CBA の順に一直線上に並ぶ : +2 // ACB, BCA の順に一直線上に並ぶ : 0 // BAC, CAB の順に一直線上に並ぶ : -2 int iSP(const Vec2& a, const Vec2& b, const Vec2& c); // 角ABC が鋭角 : 0, 直角 : 1, 鈍角 : 2 int angle_type(const Vec2& a, const Vec2& b, const Vec2& c); // 距離 LD distance(const Vec2& v1, const Vec2& v2); LD distance(const Vec2& v, const Line& l); LD distance(const Vec2& v, const Segment& s); LD distance(const Vec2& v, const Circle& c); LD distance(const Line& l, const Vec2& v); LD distance(const Line& l1, const Line& l2); LD distance(const Segment& s, const Vec2& v); LD distance(const Segment& s1, const Segment& s2); LD distance(const Circle& c, const Vec2& v); LD distance(const Circle& c1, const Circle& c2); // 交差判定 (内包しているときも true を返す) bool intersect(const Vec2& v1, const Vec2& v2); bool intersect(const Vec2& v, const Line& l); bool intersect(const Vec2& v, const Segment& l); bool intersect(const Vec2& v, const Circle& c); bool intersect(const Vec2& v, const Rect& r); bool intersect(const Line& l, const Vec2& v); bool intersect(const Line& l1, const Line& l2); bool intersect(const Line& l, const Circle& c); bool intersect(const Segment& l, const Vec2& v); bool intersect(const Segment& s1, const Segment& s2); bool intersect(const Segment& s, const Circle& c); bool intersect(const Circle& c, const Vec2& v); bool intersect(const Circle& c, const Line& l); bool intersect(const Circle& c, const Segment& s); bool intersect(const Circle& c1, const Circle& c2); bool intersect(const Circle& c, const Rect& r); bool intersect(const Rect& r1, const Rect& r2); bool intersect(const Rect& r, const Circle& c); // 交点 optional<Vec2> cross_point(const Line& l1, const Line& l2); optional<Vec2> cross_point(const Segment& s1, const Segment& s2); vector<Vec2> cross_points(const Line& l, const Circle& c); vector<Vec2> cross_points(const Circle& c,const Line& l); vector<Vec2> cross_points(const Circle& c1, const Circle& c2); } // namespace Geometric #line 5 "/home/yuruhiya/programming/library/Geometry/Vec2.hpp" namespace Geometric { struct Vec2 { LD x, y; static bool compare_x(const Vec2& v1, const Vec2& v2) { return v1.x < v2.x; } static bool compare_y(const Vec2& v1, const Vec2& v2) { return v1.y < v2.y; } static bool compare_xy(const Vec2& v1, const Vec2& v2) { return make_pair(v1.x, v1.y) < make_pair(v2.x, v2.y); } static bool compare_yx(const Vec2& v1, const Vec2& v2) { return make_pair(v1.y, v1.x) < make_pair(v2.y, v2.x); } constexpr Vec2() : x(0), y(0) {} constexpr Vec2(LD _x, LD _y) : x(_x), y(_y) {} Vec2(LD rad) : x(cos(rad)), y(sin(rad)) {} constexpr bool operator==(const Vec2& v) const { return Equal(x, v.x) && Equal(y, v.y); } constexpr bool operator!=(const Vec2& v) const { return !(*this == v); } constexpr bool operator<(const Vec2& v) const { return x < v.x - EPS && y < v.y - EPS; } constexpr bool operator<=(const Vec2& v) const { return x < v.x + EPS && y < v.y + EPS; } constexpr Vec2 operator+() const { return *this; } constexpr Vec2 operator-() const { return {-x, -y}; } constexpr Vec2 operator+(const Vec2& v) const { return Vec2(*this) += v; } constexpr Vec2 operator-(const Vec2& v) const { return Vec2(*this) -= v; } constexpr Vec2 operator*(const Vec2& v) const { return Vec2(*this) *= v; } constexpr Vec2 operator/(const Vec2& v) const { return Vec2(*this) /= v; } constexpr Vec2 operator+(LD n) const { return Vec2(*this) += Vec2(n, n); } constexpr Vec2 operator-(LD n) const { return Vec2(*this) -= Vec2(n, n); } constexpr Vec2 operator*(LD n) const { return Vec2(*this) *= Vec2(n, n); } constexpr Vec2 operator/(LD n) const { return Vec2(*this) /= Vec2(n, n); } constexpr Vec2& operator+=(const Vec2& v) { x += v.x; y += v.y; return *this; } constexpr Vec2& operator-=(const Vec2& v) { x -= v.x; y -= v.y; return *this; } constexpr Vec2& operator*=(const Vec2& v) { x *= v.x; y *= v.y; return *this; } constexpr Vec2& operator/=(const Vec2& v) { x /= v.x; y /= v.y; return *this; } constexpr Vec2& operator+=(LD n) { x += n; x += n; return *this; } constexpr Vec2& operator-=(LD n) { x -= n; x -= n; return *this; } constexpr Vec2& operator*=(LD n) { x *= n; x *= n; return *this; } constexpr Vec2& operator/=(LD n) { x /= n; x /= n; return *this; } constexpr LD operator[](size_t i) const { return i == 0 ? x : i == 1 ? y : 0; } LD manhattan(const Vec2& v) const { return std::abs(x - v.x) + std::abs(y - v.y); } template <class Shape2DType> LD distance(const Shape2DType& shape) const { return Geometric::distance(*this, shape); } template <class Shape2DType> bool intersects(const Shape2DType& shape) const { return Geometric::intersect(*this, shape); } constexpr LD length_square() const { return dot(*this); } LD length() const { return sqrt(length_square()); } // 内積 constexpr LD dot(const Vec2& v) const { return x * v.x + y * v.y; } // 外積 constexpr LD cross(const Vec2& v) const { return x * v.y - y * v.x; } // 正規化(長さを1にした)ベクトル Vec2 normalized() const { return *this / length(); } // 原点中心に rad 回転した座標 Vec2 rotation(LD rad) const { LD c = cos(rad), s = sin(rad); return {x * c - y * s, x * s + y * c}; } // 原点中心の円上に乗っているとしたときの偏角 LD angle() const { return atan2(y, x); } // 正射影 Vec2 projection(const Line& l) const; // 鏡映変換 Vec2 reflection(const Line& l) const; constexpr Vec2 rotate90() const { return {y, -x}; } constexpr Vec2 rotate180() const { return {-x, -y}; } constexpr Vec2 rotate270() const { return {-y, x}; } friend ostream& operator<<(ostream& os, const Vec2& v) { return os << '(' << v.x << ", " << v.y << ')'; } friend istream& operator>>(istream& is, Vec2& v) { return is >> v.x >> v.y; } }; } // namespace Geometric #line 9 "/home/yuruhiya/programming/library/Geometry/Polygon.hpp" using namespace std; namespace Geometric { struct Polygon : vector<Vec2> { public: Polygon(int n) : vector<Vec2>(n) {} Polygon(const vector<Vec2>& _p) : vector<Vec2>(_p) {} LD area() const { LD ans = 0; for (size_t i = 0; i < size(); ++i) { size_t next = i < size() - 1 ? i : 0; ans += abs(at(i).x * at(i).y - at(next).x * at(i).y); } return ans / 2; } // 凸性判定(反時計回り) bool is_convex() const { if (size() < 3) { return false; } for (size_t i = 0; i < size(); ++i) { size_t prev = i != 0 ? i - 1 : size() - 1; size_t next = i != size() - 1 ? i + 1 : 0; if (iSP(at(prev), at(i), at(next)) == -1) { return false; } } return true; } // 凸包(反時計回り) Polygon convex_hull() const { vector<Vec2> ps = *this; sort(ps.begin(), ps.end(), [](const Vec2& v1, const Vec2& v2) { return make_pair(v1.x, v1.y) < make_pair(v2.x, v2.y); }); int n = ps.size(), k = 0; Polygon res(2 * n); for (int i = 0; i < n; res[k++] = ps[i++]) { while (k >= 2 && iSP(res[k - 2], res[k - 1], ps[i]) <= 0) { --k; } } for (int i = n - 2, t = k + 1; i >= 0; res[k++] = ps[i--]) { while (k >= t && iSP(res[k - 2], res[k - 1], ps[i]) <= 0) { --k; } } res.resize(k - 1); return res; } // 凸包(一直線上の3点を含めない、反時計回り) Polygon convex_hull_no_collinear() const { vector<Vec2> ps = *this; sort(ps.begin(), ps.end(), [](const Vec2& v1, const Vec2& v2) { return make_pair(v1.x, v1.y) < make_pair(v2.x, v2.y); }); int n = ps.size(), k = 0; Polygon res(2 * n); for (int i = 0; i < n; res[k++] = ps[i++]) { while (k >= 2 && iSP(res[k - 2], res[k - 1], ps[i]) != -1) { --k; } } for (int i = n - 2, t = k + 1; i >= 0; res[k++] = ps[i--]) { while (k >= t && iSP(res[k - 2], res[k - 1], ps[i]) != -1) { --k; } } res.resize(k - 1); return res; } // 直径 tuple<LD, size_t, size_t> diameter() const { size_t i_start = 0, j_start = 0; for (size_t i = 1; i < size(); ++i) { if (at(i).y > at(i_start).y) i_start = i; if (at(i).y < at(j_start).y) j_start = i; } LD max_dist = (at(i_start) - at(j_start)).length(); auto diff = [&](int i) { return at((i + 1) % size()) - at(i); }; size_t i = i_start, i_max = i_start; size_t j = j_start, j_max = j_start; do { if (diff(i).cross(diff(j)) >= 0) { j = (j + 1) % size(); } else { i = (i + 1) % size(); } if (LD d = (at(i) - at(j)).length(); max_dist < d) { max_dist = d; i_max = i; j_max = j; } } while (i != i_start || j != j_start); return {max_dist, i_max, j_max}; } // 最近点対 tuple<LD, Vec2, Vec2> closest_pair() const { vector<Vec2> points = *this; sort(points.begin(), points.end(), Vec2::compare_xy); auto dfs = [&](auto self, int left, int right) -> tuple<LD, Vec2, Vec2> { int n = right - left; if (n <= 1) { return {1e64, points[left], points[left]}; } else { int mid = (left + right) / 2; LD x = points[mid].x; auto res = min(self(self, left, mid), self(self, mid, right)); inplace_merge(points.begin() + left, points.begin() + mid, points.begin() + right, Vec2::compare_y); vector<Vec2> around; for (int i = left; i < right; ++i) { if (get<0>(res) <= abs(points[i].x - x)) { continue; } for (int size = around.size(), j = size - 1; j >= 0; --j) { if (get<0>(res) <= points[i].y - around[j].y) { break; } if (LD length = (points[i] - around[j]).length(); get<0>(res) > length) { res = {length, points[i], around[j]}; } } around.push_back(points[i]); } return res; } }; return dfs(dfs, 0, size()); } friend ostream& operator<<(ostream& os, const Polygon& p) { os << "{ "; for (size_t i = 0; i < p.size(); ++i) { if (i != 0) os << ", "; os << p[i]; } return os << " }"; } friend istream& operator>>(istream& is, Polygon& p) { for (auto& v : p) { is >> v; } return is; } }; } // namespace Geometric #line 9 "/home/yuruhiya/programming/library/Geometry/Line.hpp" using namespace std; namespace Geometric { namespace internal { struct LineBase { protected: constexpr LineBase() = default; constexpr LineBase(const Vec2& _begin, const Vec2& _end) : begin(_begin), end(_end) {} constexpr LineBase(LD begin_x, LD begin_y, LD end_x, LD end_y) : begin(begin_x, begin_y), end(end_x, end_y) {} public: Vec2 begin, end; constexpr Vec2 vec() const { return end - begin; } constexpr Vec2 counter_vec() const { return begin - end; } // 平行判定 constexpr bool is_parallel(const LineBase& l) const { return sgn(vec().cross(l.vec())) == 0; } // 直交判定 constexpr bool is_orthogonal(const LineBase& l) const { return sgn(vec().dot(l.vec())) == 0; } friend ostream& operator<<(ostream& os, const LineBase& l) { return os << '(' << l.begin << ", " << l.end << ')'; } friend istream& operator>>(istream& is, LineBase& l) { return is >> l.begin >> l.end; } }; } // namespace internal struct Line : internal::LineBase { Line() = default; Line(const Vec2& _begin, const Vec2& _end) : LineBase(_begin, _end) {} constexpr Line(LD begin_x, LD begin_y, LD end_x, LD end_y) : LineBase(begin_x, begin_y, end_x, end_y) {} Line(const LineBase& l) : LineBase(l) {} template <class Shape2DType> LD distance(const Shape2DType& shape) const { return Geometric::distance(*this, shape); } template <class Shape2DType> bool intersects(const Shape2DType& shape) const { return Geometric::intersect(*this, shape); } template <class Shape2DType> optional<Vec2> cross_point(const Shape2DType& shape) const { return Geometric::cross_point(*this, shape); } template <class Shape2DType> vector<Vec2> cross_points(const Shape2DType& shape) const { return Geometric::cross_points(*this, shape); } // ax + by + c = 0 の式に変形する tuple<LD, LD, LD> abc() const { if (sgn(begin.x - end.x) == 0) { return {1, 0, -begin.x}; } else { LD slope = (end.y - begin.y) / (end.x - begin.x); return {slope, -1, begin.y - begin.x * slope}; } } }; struct Segment : internal::LineBase { Segment() = default; Segment(const Vec2& _begin, const Vec2& _end) : LineBase(_begin, _end) {} constexpr Segment(LD begin_x, LD begin_y, LD end_x, LD end_y) : LineBase(begin_x, begin_y, end_x, end_y) {} Segment(const LineBase& l) : LineBase(l) {} template <class Shape2DType> LD distance(const Shape2DType& shape) const { return Geometric::distance(*this, shape); } template <class Shape2DType> bool intersects(const Shape2DType& shape) const { return Geometric::intersect(*this, shape); } template <class Shape2DType> optional<Vec2> cross_point(const Shape2DType& shape) const { return Geometric::cross_point(*this, shape); } template <class Shape2DType> vector<Vec2> cross_points(const Shape2DType& shape) const { return Geometric::cross_points(*this, shape); } }; } // namespace Geometric #line 6 "/home/yuruhiya/programming/library/Geometry/Circle.hpp" using namespace std; namespace Geometric { struct Circle { Vec2 center; LD r; constexpr Circle() : center(), r(0) {} constexpr Circle(LD _r) : center(), r(_r) {} constexpr Circle(LD _x, LD _y, LD _r) : center(_x, _y), r(_r) {} constexpr Circle(const Vec2& _c, LD _r) : center(_c), r(_r) {} constexpr bool operator==(const Circle& c) const { return center == c.center && Equal(r, c.r); } constexpr bool operator!=(const Circle& c) const { return !(*this == c); } constexpr Circle& operator+(const Vec2& v) const { return Circle(*this) += v; } constexpr Circle& operator-(const Vec2& v) const { return Circle(*this) -= v; } constexpr Circle& operator+=(const Vec2& v) { center += v; return *this; } constexpr Circle& operator-=(const Vec2& v) { center -= v; return *this; } constexpr LD top_y() const { return center.y - r; } constexpr LD bottom_y() const { return center.y + r; } constexpr LD left_x() const { return center.x - r; } constexpr LD right_x() const { return center.x + r; } constexpr Vec2 top() const { return center - Vec2(0, r); } constexpr Vec2 bottom() const { return center + Vec2(0, r); } constexpr Vec2 left() const { return center - Vec2(r, 0); } constexpr Vec2 right() const { return center + Vec2(r, 0); } constexpr LD area() const { return r * r * PI; } constexpr LD perimeter() const { return 2 * r * PI; } template <class Shape2DType> LD distance(const Shape2DType& shape) const { return Geometric::distance(*this, shape); } template <class Shape2DType> bool intersects(const Shape2DType& shape) const { return Geometric::intersect(*this, shape); } template <class Shape2DType> vector<Vec2> cross_points(const Shape2DType& shape) const { return Geometric::cross_points(*this, shape); } bool contains(const Circle& c) const { return center.distance(c.center) + c.r < r - EPS; } bool tangent(const Circle& c) const { LD l1 = center.distance(c.center), l2 = r, l3 = c.r; return Equal(l1 + l2 + l3, max({l1, l2, l3}) * 2); } friend ostream& operator<<(ostream& os, const Circle& c) { return os << '(' << c.center.x << ',' << c.center.y << ',' << c.r << ')'; } friend istream& operator>>(istream& is, Circle& c) { return is >> c.center >> c.r; } }; } // namespace Geometric #line 5 "/home/yuruhiya/programming/library/Geometry/Rect.hpp" using namespace std; namespace Geometric { struct Rect { Vec2 pos, size; constexpr Rect() {} constexpr Rect(LD _w, LD _h) : size(_w, _h) {} constexpr Rect(const Vec2& _size) : size(_size) {} constexpr Rect(LD _x, LD _y, LD _w, LD _h) : pos(_x, _y), size(_w, _h) {} constexpr Rect(const Vec2& _pos, const Vec2& _size) : pos(_pos), size(_size) {} constexpr bool operator==(const Rect& r) const { return pos == r.pos && size == r.size; } constexpr bool operator!=(const Rect& r) const { return !(*this == r); } constexpr Rect operator+(const Vec2& v) const { return Rect(*this) += v; } constexpr Rect operator-(const Vec2& v) const { return Rect(*this) -= v; } constexpr Rect& operator+=(const Vec2& v) { pos += v; return *this; } constexpr Rect& operator-=(const Vec2& v) { pos -= v; return *this; } constexpr Rect& set_center(const Vec2& _pos) { pos = _pos - size / 2; return *this; } constexpr LD left() const { return pos.x; } constexpr LD right() const { return pos.x + size.x; } constexpr LD top() const { return pos.y; } constexpr LD bottom() const { return pos.y + size.y; } constexpr Vec2 top_left() const { return pos; } constexpr Vec2 top_right() const { return pos + Vec2(size.x, 0); } constexpr Vec2 bottom_left() const { return pos + Vec2(0, size.y); } constexpr Vec2 bottom_right() const { return pos + size; } constexpr Vec2 center() const { return pos + size / 2; } constexpr LD area() const { return size.x * size.y; } constexpr LD perimeter() const { return (size.x + size.y) * 2; } template <class Shape2DType> LD distance(const Shape2DType& shape) const { return Geometric::distance(*this, shape); } template <class Shape2DType> bool intersects(const Shape2DType& shape) const { return Geometric::intersect(*this, shape); } constexpr bool contains(const Rect& r) const { return top_left() <= r.top_left() && r.bottom_right() <= bottom_right(); } constexpr bool contains(const Circle& c) const { return top_left() <= Vec2(c.left_x(), c.top_y()) && Vec2(c.right_x(), c.bottom_y()) <= bottom_right(); } friend ostream& operator<<(ostream& os, const Rect& r) { return os << '(' << r.pos << ',' << r.size << ')'; } friend istream& operator>>(istream& is, Rect& r) { return is >> r.pos >> r.size; } }; } // namespace Geometric #line 8 "/home/yuruhiya/programming/library/Geometry/Triangle.hpp" using namespace std; namespace Geometric { struct Triangle { Vec2 p1, p2, p3; static LD area(LD a, LD b, LD c) { LD s = (a + b + c) / 2; return sqrt(s * (s - a) * (s - b) * (s - c)); } Triangle() = default; Triangle(const Vec2& _p1, const Vec2& _p2, const Vec2& _p3) : p1(_p1), p2(_p2), p3(_p3) { assert(abs(iSP(p1, p2, p3)) == 1); } tuple<LD, LD, LD> sides() const { return {p2.distance(p3), p1.distance(p3), p1.distance(p2)}; } LD area() const { auto [l1, l2, l3] = sides(); return area(l1, l2, l3); } // 内接円 Circle incircle() const { auto [l1, l2, l3] = sides(); LD s = l1 + l2 + l3; LD x = (p1.x * l1 + p2.x * l2 + p3.x * l3) / s; LD y = (p1.y * l1 + p2.y * l2 + p3.y * l3) / s; s /= 2; LD r = sqrt((s - l1) * (s - l2) * (s - l3) / s); return Circle(x, y, r); } // 外接円 Circle cirnumscribed_circle() const { Line l1((p1 + p2) / 2, (p1 + p2) / 2 + (p1 - p2).rotate270()); Line l2((p1 + p3) / 2, (p1 + p3) / 2 + (p1 - p3).rotate270()); Vec2 center = *l1.cross_point(l2); return Circle(center, center.distance(p1)); } friend ostream& operator<<(ostream& os, const Triangle& t) { return os << '(' << t.p1 << ", " << t.p2 << ", " << t.p3 << ')'; } friend istream& operator>>(istream& is, Triangle& t) { return is >> t.p1 >> t.p2 >> t.p3; } }; } // namespace Geometric #line 8 "/home/yuruhiya/programming/library/Geometry/Geometric.cpp" namespace Geometric { constexpr bool Equal(LD a, LD b) { return a < b ? b - a < EPS : a - b < EPS; } // a > 0 : +1 // a == 0 : 0 // a < 0 : -1 constexpr int sgn(LD a) { return a < -EPS ? -1 : a > EPS ? 1 : 0; } constexpr LD deg_to_rad(LD deg) { return deg * PI / 180; } constexpr LD rad_to_deg(LD rad) { return rad * 180 / PI; } Vec2 Vec2::projection(const Line& l) const { return l.begin + l.vec().normalized() * (*this - l.begin).dot(l.vec()) / l.vec().length(); } Vec2 Vec2::reflection(const Line& l) const { return *this + (projection(l) - *this) * 2; } int iSP(const Vec2& a, const Vec2& b, const Vec2& c) { int flag = sgn((b - a).cross(c - a)); if (flag != 0) { return flag; } else { if (sgn((b - a).dot(c - b)) > 0) { return 2; } else if (sgn((a - b).dot(c - a)) > 0) { return -2; } else { return 0; } } } int angle_type(const Vec2& a, const Vec2& b, const Vec2& c) { if (int f = sgn((a - b).dot(c - b)); f > 0) { return 0; } else if (f == 0) { return 1; } else { return 2; } } LD distance(const Vec2& v1, const Vec2& v2) { return hypot(v1.x - v2.x, v1.y - v2.y); } LD distance(const Vec2& v, const Line& l) { return abs(l.vec().cross(v - l.begin) / l.vec().length()); } LD distance(const Vec2& v, const Segment& s) { if (sgn(s.vec().dot(v - s.begin)) < 0 || sgn(s.counter_vec().dot(v - s.end)) < 0) { return min(v.distance(s.begin), v.distance(s.end)); } else { return Line(s).distance(v); } } LD distance(const Vec2& v, const Circle& c) { return max<LD>(0, c.center.distance(v) - c.r); } LD distance(const Line& l, const Vec2& v) { return distance(v, l); } LD distance(const Line& l1, const Line& l2) { return l1.is_parallel(l2) ? l1.distance(l2.begin) : 0; } LD distance(const Segment& s, const Vec2& v) { return distance(v, s); } LD distance(const Segment& s1, const Segment& s2) { if (intersect(s1, s2)) { return 0; } else { return min({distance(s1, s2.begin), distance(s1, s2.end), distance(s1.begin, s2), distance(s1.end, s2)}); } } LD distance(const Circle& c, const Vec2& v) { return distance(v, c); } LD distance(const Circle& c1, const Circle& c2) { return max<LD>(0, distance(c1.center, c2.center) - (c1.r + c2.r)); } bool intersect(const Vec2& v1, const Vec2& v2) { return v1 == v2; } bool intersect(const Vec2& v, const Line& l) { return abs(iSP(v, l.begin, l.end)) != -1; } bool intersect(const Vec2& v, const Segment& l) { return iSP(l.begin, l.end, v) == 0; } bool intersect(const Vec2& v, const Circle& c) { return c.center.distance(v) < c.r + EPS; } bool intersect(const Vec2& v, const Rect& r) { return r.pos <= v && v <= r.bottom_right(); } bool intersect(const Line& l, const Vec2& v) { return intersect(v, l); } bool intersect(const Line& l1, const Line& l2) { return !l1.is_parallel(l2); } bool intersect(const Line& l, const Circle& c) { return sgn(distance(c.center, l) - c.r) <= 0; } bool intersect(const Segment& l, const Vec2& v) { return intersect(v, l); } bool intersect(const Segment& s1, const Segment& s2) { return iSP(s1.begin, s1.end, s2.begin) * iSP(s1.begin, s1.end, s2.end) <= 0 && iSP(s2.begin, s2.end, s1.begin) * iSP(s2.begin, s2.end, s1.end) <= 0; } bool intersect(const Segment& s, const Circle& c) { return sgn(distance(c.center, s) - c.r) <= 0; } bool intersect(const Circle& c, const Vec2& v) { return intersect(v, c); } bool intersect(const Circle& c, const Line& l) { return intersect(l, c); } bool intersect(const Circle& c, const Segment& s) { return intersect(s, c); } bool intersect(const Circle& c1, const Circle& c2) { return sgn(distance(c1.center, c2.center) - (c1.r + c2.r)) <= 0; } bool intersect(const Circle& c, const Rect& r) { return Rect(r.pos - Vec2(0, c.r), r.size + Vec2(0, c.r * 2)).intersects(c.center) || Rect(r.pos - Vec2(c.r, 0), r.size + Vec2(c.r * 2, 0)).intersects(c.center) || c.intersects(r.top_left()) || c.intersects(r.top_right()) || c.intersects(r.bottom_left()) || c.intersects(r.bottom_right()); } bool intersect(const Rect& r1, const Rect& r2) { return max(r1.left(), r2.left()) < min(r1.right(), r2.right()) + EPS && max(r1.top(), r2.top()) < min(r1.bottom(), r2.bottom()) + EPS; } bool intersect(const Rect& r, const Circle& c) { return intersect(c, r); } optional<Vec2> cross_point(const Line& l1, const Line& l2) { if (intersect(l1, l2)) { // return begin + vec() * abs((l.end - begin).cross(l.vec()) / vec().cross(l.vec())); auto [a, b, c] = l1.abc(); auto [A, B, C] = l2.abc(); LD d = A * b - a * B; return Vec2((B * c - b * C) / d, (a * C - A * c) / d); } else { return nullopt; } } optional<Vec2> cross_point(const Segment& s1, const Segment& s2) { if (intersect(s1, s2)) { return cross_point(Line(s1), Line(s2)); } else { return nullopt; } } vector<Vec2> cross_points(const Line& l, const Circle& c) { LD dist = distance(l, c.center); if (int f = sgn(c.r - dist); f == 1) { LD x = sqrt(c.r * c.r - dist * dist); Vec2 p = c.center.projection(l); return {p + l.vec().normalized() * x, p + l.counter_vec().normalized() * x}; } else if (f == 0) { return {c.center.projection(l)}; } else { return {}; } } vector<Vec2> cross_points(const Circle& c, const Line& l) { return cross_points(l, c); } vector<Vec2> cross_points(const Circle& c1, const Circle& c2) { Vec2 vec = (c1.center - c2.center).normalized(); // c2 -> c1 LD dist = c1.center.distance(c2.center); if (c1.contains(c2) || c2.contains(c1)) { return {}; } else if (sgn(dist - c1.r - c2.r) == 0) { return {c2.center + vec * c2.r}; } else if (sgn(c1.r + dist - c2.r) == 0) { return {c1.center + vec * c1.r}; } else if (sgn(c2.r + dist - c1.r) == 0) { return {c2.center + vec.rotate180() * c2.r}; } else if (intersect(c1, c2)) { LD area = Triangle::area(dist, c1.r, c2.r); LD y = 2 * area / dist, x = sqrt(c1.r * c1.r - y * y); LD r1_s = c1.r * c1.r, r2_s = c2.r * c2.r, dist_s = dist * dist; Vec2 h = c1.center + vec * (r2_s < r1_s + dist_s ? -x : x), v2 = vec.rotate90() * y; return {h + v2, h - v2}; } else { return {}; } } } // namespace Geometric #line 4 "a.cpp" int main() { Geometric::Polygon p(5); rep(i, 5) in(p[i]); do { if (p.convex_hull_no_collinear().size() == 5) { dump(p.convex_hull_no_collinear()); out.exit("YES"); } } while (next_permutation(all(p))); out("NO"); }