# | Submission time | Handle | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
1011141 | 2024-06-29T22:46:07 Z | crimson231 | Tapestries (POI13_gob) | C++17 | 17 ms | 524 KB |
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <algorithm> #include <cmath> #include <cstring> #include <cassert> #include <vector> typedef long long ll; typedef long double ld; const ll INF = 1e17; const int LEN = 1e3 + 1; const ld TOL = 1e-7; const ll MOD = 1'000'000'007; const ll DEN = 1LL << 32; inline int sign(const ld& x) { return x < -TOL ? -1 : x > TOL; } inline bool zero(const ld& x) { return !sign(x); } inline ll sq(int x) { return (ll)x * x; } inline ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); } int N, M, T, Q; char sc; struct BigInt { ll hi, lo; inline BigInt(ll HI = 0, ll LO = 0) : hi(HI), lo(LO) {} inline BigInt operator - () const { return { -hi, -lo }; } inline BigInt norm() const { if (lo < 0) return -*this; return *this; }//den < 0 inline bool operator < (const BigInt& p) const { return hi == p.hi ? lo < p.lo : hi < p.hi; } inline bool operator == (const BigInt& p) const { return hi == p.hi && lo == p.lo; } }; inline BigInt mul(ll a, ll b) { assert(0 < b && b < DEN); int m = a < 0 ? -1 : 1; if (m < 0) a *= -1; ll hi = (a / DEN) * b; ll lo = (a % DEN) * b; hi += lo / DEN; lo %= DEN; return BigInt(m * hi, m * lo); } inline bool cmp_frac(BigInt p, BigInt q) { p = p.norm(); q = q.norm(); return mul(p.hi, q.lo) < mul(q.hi, p.lo); } inline bool eq_frac(BigInt p, BigInt q) { p = p.norm(); q = q.norm(); return mul(p.hi, q.lo) == mul(q.hi, p.lo); } struct Pos { ll x, y; ll den; bool dark; inline Pos(ll X = 0, ll Y = 0, ll d = 1, bool S = 0) : x(X), y(Y), den(d), dark(S) {} inline bool operator == (const Pos& p) const { return x == p.x && y == p.y; } inline bool operator < (const Pos& p) const { return x == p.x ? y < p.y : x < p.x; } inline Pos operator + (const Pos& p) const { return { x + p.x, y + p.y }; } inline Pos operator - (const Pos& p) const { return { x - p.x, y - p.y }; } inline Pos operator * (const ll& n) const { return { x * n, y * n }; } inline Pos operator / (const ll& n) const { return { x / n, y / n }; } inline ll operator * (const Pos& p) const { return x * p.x + y * p.y; } inline ll operator / (const Pos& p) const { return x * p.y - y * p.x; } inline Pos operator - () const { return { -x, -y, den }; } inline Pos operator ~ () const { return { -y, x, den }; } inline ll Euc() const { return x * x + y * y; } inline friend std::istream& operator >> (std::istream& is, Pos& p) { is >> p.x >> p.y; return is; } inline friend std::ostream& operator << (std::ostream& os, const Pos& p) { os << p.x << " " << p.y; return os; } } H[LEN]; const Pos O = { 0, 0 }; typedef std::vector<Pos> Polygon; struct Line {//ax + by = c Pos s; ll c; inline Line(Pos ps = Pos(0, 0), Pos pe = Pos(0, 0)) { s = ~(pe - ps); c = s * ps; } friend std::ostream& operator << (std::ostream& os, const Line& l) { os << l.s << " " << l.c; return os; } }; inline Pos intersection(const Line& l1, const Line& l2) { Pos s = l1.s * l2.c - l2.s * l1.c; s.den = l1.s / l2.s; return ~s; } //Pos intersection(const Line& l1, const Line& l2) { // Pos v1 = l1.s, v2 = l2.s; // ld det = v1 / v2; // return { // (l1.c * v2.y - l2.c * v1.y) / det, // (l2.c * v1.x - l1.c * v2.x) / det, // }; //} inline ll cross(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) / (d3 - d2); } inline ll cross(const Pos& d1, const Pos& d2, const Pos& d3, const Pos& d4) { return (d2 - d1) / (d4 - d3); } inline ll dot(const Pos& d1, const Pos& d2, const Pos& d3) { return (d2 - d1) * (d3 - d2); } inline int ccw(const Pos& d1, const Pos& d2, const Pos& d3) { ll ret = cross(d1, d2, d3); return ret < 0 ? -1 : !!ret; } inline bool not_zig_zag(const int& i) { Pos& p1 = H[(i - 1 + N) % N], & p2 = H[i]; Pos& p3 = H[(i + 1) % N], & p4 = H[(i + 2) % N]; return ccw(p1, p2, p3) == ccw(p2, p3, p4); } bool inner_check(const Pos& p1, const Pos& p2, const Pos& p3, const Pos& q) { return cross(p1, p2, q) < 0 && cross(p2, p3, q) < 0 && cross(p3, p1, q) < 0; } inline bool closer(const Pos& p1, const Pos& p2, const Pos& cur, const Pos& candi) { return std::abs(cross(p1, p2, cur)) > std::abs(cross(p1, p2, candi)); } inline BigInt dot(const Pos& vec, const Pos& inx) { return BigInt(vec * inx, inx.den); } inline bool include(const Line& l, const Pos& inx) { return cmp_frac(dot(l.s, inx), BigInt(l.c, 1)); } inline bool on_line(const Line& l, const Pos& inx) { return eq_frac(dot(l.s, inx), BigInt(l.c, 1)); } inline std::string half_plane_intersection_include_x(const int& x = -1) { //x == -1 : no dark wall //x != -1 : only one dark wall //the two walls next to the dark wall //must have a zigzag shape to be bright. if (x != -1 && not_zig_zag(x)) return "NIE"; int sz = (x == -1 ? N : x + 1); int i = (x == -1 ? 0 : x); for (i; i < sz; i++) {//half_plane_intersection must include i1-i2 Pos& i1 = H[i], & i2 = H[(i + 1) % N]; Pos vec = i2 - i1; bool rvs = 0; BigInt hi = { INF, 1 }, lo = { -INF, 1 }; for (int j = 0; j < N; j++) { if (j == i) continue; Pos& j1 = H[j], & j2 = H[(j + 1) % N]; ll det = cross(i1, i2, j1, j2); if (!det) { if (cross(j1, j2, i1) >= 0) { rvs = 1; break; } continue; } BigInt inx = dot(vec, intersection(Line(i1, i2), Line(j1, j2))); if (det < 0 && cmp_frac(inx, hi)) hi = inx; else if (det > 0 && cmp_frac(lo, inx)) lo = inx; } if (cmp_frac(lo, hi) && !rvs) return "TAK"; } return "NIE"; } inline std::string query() { std::cin >> N; for (int i = 0; i < N; i++) std::cin >> H[i]; int illum = 0, dark = -1; for (int i = 0; i < N; i++) { std::cin >> sc; H[i].dark = sc == 'C'; if (!H[i].dark) illum++; if (H[i].dark) dark = i; } if (illum < 3) return "NIE"; if (illum >= N - 1) return half_plane_intersection_include_x(dark); int i1 = 0, i2 = 0, i3 = 0; while (1) {//merge all dark walls //a room with only dark walls, leaving only a door. if (N <= 3) return "NIE";//at least one must be dark. i1 = 0; i2 = 0; i3 = 0; for (i1 = 0; i1 < N; i1++) { i2 = (i1 + 1) % N; i3 = (i2 + 1) % N; if (H[i1].dark && H[i2].dark && cross(H[i1], H[i2], H[i3]) < 0) break; } if (i1 == N) break;//all dark walls are unattached. int c = -1;//closest point to wall i1-i2 for (int i = 0; i < N; i++) { if (i == i1 || i == i2 || i == i3) continue; if (inner_check(H[i1], H[i2], H[i3], H[i])) { if (c == -1 || closer(H[i1], H[i2], H[c], H[i])) c = i; } } if (c == -1) {//merge two dark walls for (int i = i2 + 1; i < N; i++) H[i - 1] = H[i]; N--; continue; } int c1 = i2, c2 = c; if (c2 < c1) std::swap(c1, c2); bool dark_hi = 1, dark_lo = 1; for (int i = 0; i < N; i++) { if (!H[i].dark) { if (c1 <= i && i < c2) dark_hi = 0; else dark_lo = 0; } } if (!dark_hi && !dark_lo) return "NIE";//both sides of a dark passage must be bright. if (dark_hi) {//merge dark walls int len = c2 - c1 - 1; for (int i = c2; i < N; i++) H[i - len] = H[i]; N -= len; } if (dark_lo) {//merge dark walls for (int i = c1; i <= c2; i++) H[i - c1] = H[i]; N = c2 - c1 + 1; } } i1 = 0; while (!H[i1].dark) i1++; i2 = i1 + 1; while (i2 < N && !H[i2].dark) i2++; //cnly one dark wall if (i2 == N) return half_plane_intersection_include_x(i1); //two or more dark walls //all dark walls must intersect at a point //and all left half-plane of light wall must include that point. Pos& w1 = H[i1], & w2 = H[(i1 + 1) % N]; Pos& w3 = H[i2], & w4 = H[(i2 + 1) % N]; if (!cross(w1, w2, w3, w4)) return "NIE"; Pos inx = intersection(Line(w1, w2), Line(w3, w4)); for (int i = 0; i < N; i++) { Pos& p1 = H[i], & p2 = H[(i + 1) % N]; if (p1.dark) { if (p2.dark) return "NIE"; if (not_zig_zag(i)) return "NIE"; if (!on_line(Line(p1, p2), inx)) return "NIE"; } if (!p1.dark && !include(Line(p1, p2), inx)) return "NIE"; } return "TAK"; } inline void solve() { std::cin.tie(0)->sync_with_stdio(0); std::cout.tie(0); std::cin >> T; while (T--) std::cout << query() << "\n"; return; } int main() { solve(); return 0; }//boj8237 Tapestries refer to model_code (oj.uz)
Compilation message
# | Verdict | Execution time | Memory | Grader output |
---|---|---|---|---|
1 | Correct | 0 ms | 344 KB | Output is correct |
2 | Correct | 0 ms | 348 KB | Output is correct |
3 | Correct | 0 ms | 348 KB | Output is correct |
4 | Correct | 0 ms | 348 KB | Output is correct |
5 | Correct | 0 ms | 348 KB | Output is correct |
6 | Correct | 0 ms | 348 KB | Output is correct |
7 | Correct | 1 ms | 348 KB | Output is correct |
8 | Correct | 1 ms | 348 KB | Output is correct |
9 | Correct | 17 ms | 348 KB | Output is correct |
10 | Correct | 11 ms | 524 KB | Output is correct |