#line 1 "a.cpp" #line 2 "/home/nok0/documents/programming/library/template/header.hpp" #include #line 3 "/home/nok0/documents/programming/library/template/def_const.hpp" const int inf = 1000000000; const long long INF = 1000000000000000000ll; #line 4 "/home/nok0/documents/programming/library/template/debug.hpp" namespace viewer { void view(const long long &e) { if(e == INF) std::cerr << "INF"; else if(e == -INF) std::cerr << "-INF"; else std::cerr << e; } void view(const int &e) { if(e == inf) std::cerr << "inf"; else if(e == -inf) std::cerr << "-inf"; else std::cerr << e; } template void view(const T &e) { std::cerr << e; } template void view(const std::pair &p) { std::cerr << "("; view(p.first); std::cerr << ", "; view(p.second); std::cerr << ")"; } template void view(const std::tuple &p) { std::cerr << "("; view(std::get<0>(p)); std::cerr << ", "; view(std::get<1>(p)); std::cerr << ", "; view(std::get<2>(p)); std::cerr << ")"; } template void view(const std::tuple &p) { std::cerr << "("; view(std::get<0>(p)); std::cerr << ", "; view(std::get<1>(p)); std::cerr << ", "; view(std::get<2>(p)); std::cerr << ", "; view(std::get<3>(p)); std::cerr << ")"; } template void view(const std::set &s) { if(s.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(auto &t : s) { view(t); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::unordered_set &s) { if(s.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(auto &t : s) { view(t); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::multiset &s) { if(s.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(auto &t : s) { view(t); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::unordered_multiset &s) { if(s.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(auto &t : s) { view(t); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::vector &v) { if(v.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(const auto &e : v) { view(e); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::array &v) { if(v.empty()) { std::cerr << "{ }"; return; } std::cerr << "{ "; for(const auto &e : v) { view(e); std::cerr << ", "; } std::cerr << "\b\b }"; } template void view(const std::vector> &vv) { std::cerr << "{\n"; for(const auto &v : vv) { std::cerr << "\t"; view(v); std::cerr << '\n'; } std::cerr << "}"; } template void view(const std::vector> &v) { std::cerr << "{\n"; for(const auto &c : v) { std::cerr << "\t("; view(c.first); std::cerr << ", "; view(c.second); std::cerr << ")\n"; } std::cerr << "}"; } template void view(const std::vector> &v) { if(v.empty()) { std::cerr << "{ }"; return; } std::cerr << '{'; for(const auto &t : v) { std::cerr << "\n\t"; view(t); std::cerr << ","; } std::cerr << "\n}"; } template void view(const std::vector> &v) { if(v.empty()) { std::cerr << "{ }"; return; } std::cerr << '{'; for(const auto &t : v) { std::cerr << "\n\t"; view(t); std::cerr << ","; } std::cerr << "\n}"; } template void view(const std::map &m) { std::cerr << "{\n"; for(const auto &t : m) { std::cerr << "\t["; view(t.first); std::cerr << "] : "; view(t.second); std::cerr << '\n'; } std::cerr << "}"; } template void view(const std::unordered_map &m) { std::cerr << "{\n"; for(const auto &t : m) { std::cerr << "\t["; view(t.first); std::cerr << "] : "; view(t.second); std::cerr << '\n'; } std::cerr << "}"; } } // namespace viewer // when compiling : g++ foo.cpp -DLOCAL #ifdef LOCAL void debug_out() {} template void debug_out(Head H, Tail... T) { viewer::view(H); std::cerr << ", "; debug_out(T...); } #define debug(...) \ do { \ std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \ debug_out(__VA_ARGS__); \ std::cerr << "\b\b]\n"; \ } while(0) #define dump(x) \ do { \ std::cerr << __LINE__ << " " << #x << " : "; \ viewer::view(x); \ std::cerr << '\n'; \ } while(0) #else #define debug(...) (void(0)) #define dump(x) (void(0)) #endif #line 3 "/home/nok0/documents/programming/library/template/def_name.hpp" #define pb push_back #define eb emplace_back #define SZ(x) ((int)(x).size()) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define popcnt(x) __builtin_popcountll(x) template using V = std::vector; template using VV = std::vector>; template using pqup = std::priority_queue, std::greater>; using ll = long long; using ld = long double; using int128 = __int128_t; using pii = std::pair; using pll = std::pair; #line 3 "/home/nok0/documents/programming/library/template/fast_io.hpp" struct fast_io { fast_io() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout << std::fixed << std::setprecision(15); } } fast_io_; #line 3 "/home/nok0/documents/programming/library/template/input.hpp" template std::istream &operator>>(std::istream &is, std::pair &p) { is >> p.first >> p.second; return is; } template std::istream &operator>>(std::istream &is, std::vector &v) { for(T &i : v) is >> i; return is; } std::istream &operator>>(std::istream &is, __int128_t &a) { std::string s; is >> s; __int128_t ret = 0; for(int i = 0; i < (int)s.length(); i++) if('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0'; a = ret * (s[0] == '-' ? -1 : 1); return is; } namespace scanner { void scan(int &a) { std::cin >> a; } void scan(long long &a) { std::cin >> a; } void scan(std::string &a) { std::cin >> a; } void scan(char &a) { std::cin >> a; } void scan(char a[]) { std::scanf("%s", a); } void scan(double &a) { std::cin >> a; } void scan(long double &a) { std::cin >> a; } template void scan(std::pair &p) { std::cin >> p; } template void scan(std::vector &a) { std::cin >> a; } void INPUT() {} template void INPUT(Head &head, Tail &...tail) { scan(head); INPUT(tail...); } } // namespace scanner #define VEC(type, name, size) \ std::vector name(size); \ scanner::INPUT(name) #define VVEC(type, name, h, w) \ std::vector> name(h, std::vector(w)); \ scanner::INPUT(name) #define INT(...) \ int __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #define LL(...) \ long long __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #define STR(...) \ std::string __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #define CHAR(...) \ char __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #define DOUBLE(...) \ double __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #define LD(...) \ long double __VA_ARGS__; \ scanner::INPUT(__VA_ARGS__) #line 3 "/home/nok0/documents/programming/library/template/math.hpp" template inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; } template inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; } template T divup(T x, T y) { return (x + y - 1) / y; } template T POW(T a, long long n) { T ret = 1; while(n) { if(n & 1) ret *= a; a *= a; n >>= 1; } return ret; } long long POW(long long a, long long n, const int mod) { long long ret = 1; a = (a % mod + mod) % mod; while(n) { if(n & 1) (ret *= a) %= mod; (a *= a) %= mod; n >>= 1; } return ret; } template T bin_search(T ok, T ng, const F &f) { while(abs(ok - ng) > 1) { T mid = (ok + ng) >> 1; (f(mid) ? ok : ng) = mid; } return ok; } template T bin_search(T ok, T ng, const F &f, int loop) { for(int i = 0; i < loop; i++) { T mid = (ok + ng) / 2; (f(mid) ? ok : ng) = mid; } return ok; } #line 3 "/home/nok0/documents/programming/library/template/output.hpp" template std::ostream &operator<<(std::ostream &os, const std::pair &p) { os << p.first << " " << p.second; return os; } template std::ostream &operator<<(std::ostream &os, const std::vector &a) { for(int i = 0; i < int(a.size()); ++i) { if(i) os << " "; os << a[i]; } return os; } std::ostream &operator<<(std::ostream &dest, __int128_t &value) { std::ostream::sentry s(dest); if(s) { __uint128_t tmp = value < 0 ? -value : value; char buffer[128]; char *d = std::end(buffer); do { --d; *d = "0123456789"[tmp % 10]; tmp /= 10; } while(tmp != 0); if(value < 0) { --d; *d = '-'; } int len = std::end(buffer) - d; if(dest.rdbuf()->sputn(d, len) != len) { dest.setstate(std::ios_base::badbit); } } return dest; } template void print(const T a) { std::cout << a << '\n'; } template void print(Head H, Tail... T) { std::cout << H << ' '; print(T...); } template void printel(const T a) { std::cout << a << '\n'; } template void printel(const std::vector &a) { for(const auto &v : a) std::cout << v << '\n'; } template void printel(Head H, Tail... T) { std::cout << H << '\n'; printel(T...); } void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); } void No() { std::cout << "No\n"; } void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); } void NO() { std::cout << "NO\n"; } #line 2 "/home/nok0/documents/programming/library/template/rep.hpp" #define foa(v, a) for(auto &v : a) #define repname(a, b, c, d, e, ...) e #define rep(...) repname(__VA_ARGS__, rep3, rep2, rep1, rep0)(__VA_ARGS__) #define rep0(x) for(int rep_counter = 0; rep_counter < (x); ++rep_counter) #define rep1(i, x) for(int i = 0; i < (x); ++i) #define rep2(i, l, r) for(int i = (l); i < (r); ++i) #define rep3(i, l, r, c) for(int i = (l); i < (r); i += (c)) #define repsname(a, b, c, ...) c #define reps(...) repsname(__VA_ARGS__, reps1, reps0)(__VA_ARGS__) #define reps0(x) for(int reps_counter = 1; reps_counter <= (x); ++reps_counter) #define reps1(i, x) for(int i = 1; i <= (x); ++i) #define rrepname(a, b, c, ...) c #define rrep(...) rrepname(__VA_ARGS__, rrep1, rrep0)(__VA_ARGS__) #define rrep0(x) for(int rrep_counter = (x)-1; rrep_counter >= 0; --rrep_counter) #define rrep1(i, x) for(int i = (x)-1; i >= 0; --i) #line 3 "/home/nok0/documents/programming/library/template/vector.hpp" template int lb(const std::vector &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); } template int ub(const std::vector &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); } template void UNIQUE(std::vector &a) { std::sort(a.begin(), a.end()); a.erase(std::unique(a.begin(), a.end()), a.end()); } template std::vector press(std::vector &a) { auto res = a; UNIQUE(res); for(auto &v : a) v = lb(res, v); return res; } #define SORTname(a, b, c, ...) c #define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__) #define SORT0(a) std::sort((a).begin(), (a).end()) #define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; }) template void ADD(std::vector &a, const T x = 1) { for(auto &v : a) v += x; } template void SUB(std::vector &a, const T x = 1) { for(auto &v : a) v -= x; } template struct cum_vector { public: cum_vector() = default; template cum_vector(const std::vector &vec) : cum((int)vec.size() + 1) { for(int i = 0; i < (int)vec.size(); i++) cum[i + 1] = cum[i] + vec[i]; } T prod(int l, int r) { return cum[r] - cum[l]; } private: std::vector cum; }; std::vector> rle(const std::string &s) { const int n = s.size(); std::vector> ret; for(int l = 0; l < n;) { int r = l + 1; for(; r < n and s[l] == s[r]; r++) {} ret.emplace_back(s[l], r - l); l = r; } return ret; } template std::vector> rle(const std::vector &v) { int n = v.size(); std::vector> ret; for(int l = 0; l < n;) { int r = l + 1; for(; r < n and v[l] == v[r]; r++) {} ret.emplace_back(v[l], r - l); l = r; } return ret; } std::vector iota(int n) { std::vector p(n); std::iota(p.begin(), p.end(), 0); return p; } #line 11 "/home/nok0/documents/programming/library/template/all" using namespace std; #line 2 "a.cpp" using R = long double; using point = std::complex; using arrow = point; const R EPS(1e-10), PI(acosl(-1)); inline bool eq(const R &a, const R &b) { return fabsl(b - a) < EPS; } inline bool same_point(const point &a, const point &b) { return abs(b - a) < EPS; } /* sign of x -1: x < 0 0: x == 0 1: x > 0 */ inline int sgn(const R &x) { return fabsl(x) < EPS ? 0 : (x < 0 ? -1 : 1); } /* sign of (a-b) -1: a < b 0: a == b 1: a > b */ inline int compare(const R &a, const R &b) { return eq(a, b) ? 0 : a < b ? -1 : 1; } std::istream &operator>>(std::istream &is, point &p) { R a, b; is >> a >> b; p = point(a, b); return is; } std::ostream &operator<<(std::ostream &os, point &p) { return os << '(' << p.real() << ", " << p.imag() << ')'; } // rotate point 'p' for counter clockwise direction point rotate(const point &p, const R &theta) { return point(cosl(theta) * p.real() - sinl(theta) * p.imag(), sinl(theta) * p.real() + cosl(theta) * p.imag()); } R radian_to_degree(const R &r) { return (r * 180.0 / PI); } R degree_to_radian(const R &d) { return (d * PI / 180.0); } // get angle a-b-c (>(std::istream &is, line &a) { return is >> a.a >> a.b; } }; struct segment { point a, b; segment() = default; segment(const point &a, const point &b) : a(a), b(b) {} explicit segment(const line &ln) : a(ln.a), b(ln.b) {} friend std::ostream &operator<<(std::ostream &os, segment &seg) { return os << '[' << seg.a << " -- " << seg.b << ']'; } friend std::istream &operator>>(std::istream &is, segment &a) { return is >> a.a >> a.b; } }; line::line(const segment &seg) : a(seg.a), b(seg.b) {} struct circle { point center; R radius; circle() = default; circle(const point ¢er, const R &radius) : center(center), radius(radius) {} }; using points = std::vector; using polygon = std::vector; using segments = std::vector; using lines = std::vector; using circles = std::vector; R cross(const point &a, const point &b) { return real(a) * imag(b) - imag(a) * real(b); } R dot(const point &a, const point &b) { return real(a) * real(b) + imag(a) * imag(b); } enum CCW { ONLINE_FRONT = -2, CLOCKWISE = -1, ON_SEGMENT = 0, COUNTER_CLOCKWISE = 1, ONLINE_BACK = 2, }; int ccw(const point &a, point b, point c) { b -= a, c -= a; const R crs_b_c = cross(b, c); if(crs_b_c > EPS) return CCW::COUNTER_CLOCKWISE; if(crs_b_c < -EPS) return CCW::CLOCKWISE; if(dot(b, c) < -EPS) return CCW::ONLINE_BACK; if(norm(b) + EPS < norm(c)) return CCW::ONLINE_FRONT; return CCW::ON_SEGMENT; } bool parallel(const arrow &a, const arrow &b) { return eq(cross(a, b), R(0)); } bool parallel(const line &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); } bool parallel(const line &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); } bool parallel(const segment &a, const line &b) { return parallel(a.b - a.a, b.b - b.a); } bool parallel(const segment &a, const segment &b) { return parallel(a.b - a.a, b.b - b.a); } bool orthogonal(const arrow &a, const arrow &b) { return eq(dot(a, b), R(0)); } bool orthogonal(const line &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); } bool orthogonal(const line &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); } bool orthogonal(const segment &a, const line &b) { return orthogonal(a.b - a.a, b.b - b.a); } bool orthogonal(const segment &a, const segment &b) { return orthogonal(a.b - a.a, b.b - b.a); } point projection(const line &l, const point &p) { return l.a + (l.a - l.b) * dot(p - l.a, l.a - l.b) / norm(l.a - l.b); } point projection(const segment &s, const point &p) { return projection(line(s), p); } point reflection(const line &l, const point &p) { return projection(l, p) * R(2) - p; } point reflection(const segment &s, const point &p) { return projection(line(s), p); } R distance(const point &p, const point &q); R distance(const line &l, const point &p); int number_of_common_tangents(const circle &c1, const circle &c2) { const R r1 = std::min(c1.radius, c2.radius), r2 = std::max(c1.radius, c2.radius), d = distance(c1.center, c2.center); int com = compare(r1 + r2, d); return com == 1 ? compare(d + r1, r2) + 1 : 3 - com; } // number of common points (-1: infinite) int intersect(const line &l, const point &p) { return int(abs(ccw(l.a, l.b, p)) != 1); } int intersect(const point &p, const line &l) { return intersect(l, p); } int intersect(const line &l, const line &m) { if(intersect(l, m.a) && intersect(l, m.b)) return -1; return int(!parallel(l, m)); } int intersect(const segment &s, const point &p) { return int(ccw(s.a, s.b, p) == CCW::ON_SEGMENT); } int intersect(const point &p, const segment &s) { return intersect(s, p); } int intersect(const line &l, const segment &s) { if(intersect(l, s.a) && intersect(l, s.b)) return -1; return ccw(l.a, l.b, s.a) * ccw(l.a, l.b, s.b) != 1; } int intersect(const segment &s, const line &l) { return intersect(l, s); } int intersect(const circle &c, const line &l) { R d = c.radius - distance(l, c.center); return fabsl(d) < EPS ? 1 : d > 0. ? 2 : 0; } int intersect(const line &l, const circle &c) { return intersect(c, l); } int intersect(const circle &c, const point &p) { return int(eq(c.radius, distance(c.center, p))); } int intersect(const point &p, const circle &c) { return intersect(c, p); } int intersect(const segment &s, const segment &t) { if(same_point(s.a, s.b)) return intersect(t, s.a); if(intersect(line(s), t.a) && intersect(line(s), t.b) && std::max(std::min(s.a, s.b), std::min(t.a, t.b)) < std::min(std::max(s.a, s.b), std::max(t.a, t.b))) return -1; return int(ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0); } int intersect(const circle &c, const segment &s) { const point h = projection(s, c.center); const int c0 = compare(distance(h, c.center), c.radius); if(c0 == 1) return 0; if(c0 == 0) return intersect(s, h); const int c1 = compare(distance(c.center, s.a), c.radius), c2 = compare(distance(c.center, s.b), c.radius); if(std::min(c1, c2) == -1) return int(std::max(c1, c2) >= 0); return intersect(s, h) ? 2 : 0; } int intersect(const segment &s, const circle &c) { return intersect(c, s); } int intersect(const circle &c1, const circle &c2) { return 2 - abs(2 - number_of_common_tangents(c1, c2)); } // distance of two shaps R distance(const point &a, const point &b) { return fabs(a - b); } R distance(const line &l, const point &p) { return distance(p, projection(l, p)); } R distance(const point &p, const line &l) { return distance(l, p); } R distance(const line &l, const line &m) { return parallel(l, m) ? distance(l, m.a) : 0; } R distance(const segment &s, const point &p) { const point r = projection(s, p); return intersect(s, r) ? distance(r, p) : std::min(distance(s.a, p), distance(s.b, p)); } R distance(const point &p, const segment &s) { return distance(s, p); } R distance(const segment &a, const segment &b) { if(intersect(a, b)) return R(0); return std::min({distance(a, b.a), distance(a, b.b), distance(b, a.a), distance(b, a.b)}); } R distance(const line &l, const segment &s) { if(intersect(l, s)) return 0; return std::min(distance(l, s.a), distance(l, s.b)); } R distance(const segment &s, const line &l) { return distance(l, s); } R distance(const circle &c, const point &p) { return fabsl(distance(c.center, p) - c.radius); } R distance(const point &p, const circle &c) { return distance(c, p); } R distance(const circle &c, const line &l) { return std::max(R(0), distance(l, c.center) - c.radius); } R distance(const line &l, const circle &c) { return distance(c, l); } R distance(const circle &c1, const circle &c2) { const R d = distance(c1.center, c2.center); if(d > c1.radius + c2.radius) return d - c1.radius - c2.radius; if(d < fabsl(c1.radius - c2.radius)) return fabsl(c1.radius - c2.radius) - d; return R(0); } R distance(const circle &c, const segment &s) { const point p = projection(s, c.center); const R dist_min = intersect(s, p) ? distance(c.center, p) : std::min(distance(c.center, s.a), distance(c.center, s.b)); if(dist_min > c.radius) return dist_min - c.radius; const R dist_max = std::max(distance(c.center, s.a), distance(c.center, s.b)); return dist_max < c.radius ? c.radius - dist_max : R(0); } R distance(const segment &s, const circle &c) { return distance(c, s); } point crosspoint(const line &l, const line &m) { R A = cross(l.b - l.a, m.b - m.a); R B = cross(l.b - l.a, l.b - m.a); if(eq(A, 0.)) return m.a; return m.a + (m.b - m.a) * B / A; } point crosspoint(const segment &s, const segment &t) { return crosspoint(line(s), line(t)); } point crosspoint(const segment &s, const line &l) { return crosspoint(line(s), l); } point crosspoint(const line &l, const segment &s) { return crosspoint(l, line(s)); } points crosspoints(const circle &c, const line &l) { const point pr = projection(l, c.center); const R square = c.radius * c.radius - norm(pr - c.center); switch(sgn(square)) { case 0 : return points{pr}; case -1 : return points(0); } const arrow v = (l.b - l.a) / abs(l.b - l.a) * sqrtl(square); return points{pr - v, pr + v}; } points crosspoints(const line &l, const circle &c) { return crosspoints(c, l); } points crosspoints(const circle &c, const segment &s) { points ret; for(const auto &pt : crosspoints(c, line(s))) if(intersect(s, pt)) ret.push_back(pt); return ret; } points crosspoints(const segment &s, const circle &c) { return crosspoints(c, s); } points crosspoints(const circle &c1, const circle &c2) { R d = abs(c1.center - c2.center); if(compare(d, c1.radius + c2.radius) == 1) return points(0); if(compare(d, fabsl(c1.radius - c2.radius)) == -1) return points(0); bool one_crosspoint = false; if(eq(d, c1.radius + c2.radius) || eq(d, fabsl(c1.radius - c2.radius))) one_crosspoint = true; const R alpha = acosl((c1.radius * c1.radius + d * d - c2.radius * c2.radius) / (2 * c1.radius * d)); // cosine theorem const R beta = std::arg(c2.center - c1.center); if(one_crosspoint) return points{c1.center + std::polar(c1.radius, beta + alpha)}; return points{c1.center + std::polar(c1.radius, beta + alpha), c1.center + std::polar(c1.radius, beta - alpha)}; } points tangent_points(const circle &c, const point &p) { const R square = norm(c.center - p) - c.radius * c.radius; switch(sgn(square)) { case 0 : return points{p}; case -1 : return points{}; } return crosspoints(c, circle(p, sqrtl(square))); } // common tangents of two circles lines tangents(circle c1, circle c2) { lines ret; if(c1.radius < c2.radius) std::swap(c1, c2); const R g = distance(c1.center, c2.center); if(!sgn(g)) return ret; const arrow u = (c2.center - c1.center) / g; const arrow v = rotate(u, PI * 0.5); for(const int &s : {-1, 1}) { const R h = (c1.radius + s * c2.radius) / g; if(eq(1 - h * h, 0)) { ret.emplace_back(c1.center + u * c1.radius, c1.center + (u + v) * c1.radius); } else if(1 - h * h > 0) { const point uu = u * h, vv = v * sqrtl(1 - h * h); ret.emplace_back(c1.center + (uu + vv) * c1.radius, c2.center - (uu + vv) * c2.radius * R(s)); ret.emplace_back(c1.center + (uu - vv) * c1.radius, c2.center - (uu - vv) * c2.radius * R(s)); } } return ret; } enum CONTAIN { OUT = 0, ON = 1, IN = 2 }; int contains(const polygon &poly, const point &p) { bool in = false; for(int i = 0; i < poly.size(); i++) { point a = poly[i], b = poly[(i + 1) % poly.size()]; if(ccw(a, b, p) == 0) return CONTAIN::ON; if(a.imag() > b.imag()) swap(a, b); if(a.imag() <= p.imag() && p.imag() < b.imag() && cross(a - p, b - p) < 0) in = !in; } return in ? CONTAIN::IN : CONTAIN::OUT; } int contains(const circle &c, const point &p) { return compare(c.radius, distance(c.center, p)) + 1; } bool is_convex(const polygon &p, bool pi_is_ok = true) { int n = (int)p.size(); if(pi_is_ok) { for(int i = 0; i < n; i++) if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) == -1) return false; } else { for(int i = 0; i < n; i++) if(ccw(p[i], p[(i + 1) % n], p[(i + 2) % n]) != 1) return false; } return true; } polygon convex_hull(polygon &p, bool vertices_on_edge_remain = true) { int n = (int)p.size(), k = 0; if(n <= 2) return p; sort(p.begin(), p.end()); points ch(2 * n); if(vertices_on_edge_remain) { for(int i = 0; i < n; ch[k++] = p[i++]) while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k; for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) == -1) --k; } else { for(int i = 0; i < n; ch[k++] = p[i++]) while(k >= 2 && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k; for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]) while(k >= t && ccw(ch[k - 2], ch[k - 1], p[i]) != 1) --k; } ch.resize(k - 1); return ch; } // cut the convex polygon 'U' with line 'a'-'b', then return the leftside polygon // (i.e. forall p \in (returned polygon), ccw(a, b, p) != -1) // only 0~2 points may be returned polygon convex_cut(const polygon &U, const point &a, const point &b) { polygon ret; const line l(a, b); for(int i = 0; i < U.size(); i++) { const point &now = U[i], &nxt = U[(i + 1) % U.size()]; if(ccw(l.a, l.b, now) != -1) ret.push_back(now); if(ccw(l.a, l.b, now) * ccw(l.a, l.b, nxt) == -1) ret.push_back(crosspoint(line(now, nxt), l)); } return ret; } void main_(); int main() { int t = 1; while(t--) main_(); } void main_() { INT(n, k); points rp, bp; rep(i, n) { INT(x, y, c); if(c == 1) rp.push_back(point{x, y}); else bp.push_back(point{x, y}); } if(rp.empty() or bp.empty()) { No(); return; } if(k >= 4) { auto rh = convex_hull(rp); auto bh = convex_hull(bp); bool res = 0; foa(v, rh) { if(contains(bh, v)) res = 1; } foa(v, bh) { if(contains(rh, v)) res = 1; } rep(i, SZ(rh)) { rep(j, SZ(bh)) { auto l1 = segment(rh[i], rh[(i + 1) % SZ(rh)]); auto l2 = segment(bh[i], bh[(i + 1) % SZ(bh)]); if(intersect(l1, l2)) res = 1; } } Yes(res); } else { rep(_, 2) { for(auto b : bp) { set st; for(auto r : rp) { int dx = r.real() - b.real(); int dy = r.imag() - b.imag(); int g = gcd(dx, dy); dx /= g, dy /= g; if(st.count({-dx, -dy})) { Yes(); return; } st.insert({dx, dy}); } } swap(rp, bp); } No(); } }