Submission #1126532

#TimeUsernameProblemLanguageResultExecution timeMemory
1126532PVSekharDemarcation (BOI14_demarcation)C++17
0 / 100
7 ms996 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long // const ll MOD = 998244353; const ll MOD = 1e9 + 7; const ll N = 1e5 + 2; // from jiangly's template const double TOL = 1e-9; template<class T> struct Point { T x; T y; Point(const T x_ = 0, const T y_ = 0) : x(x_), y(y_) {} template<class U> operator Point<U>() { return Point<U>(U(x), U(y)); } Point &operator+=(const Point &p) & { x += p.x; y += p.y; return *this; } Point &operator-=(const Point &p) & { x -= p.x; y -= p.y; return *this; } Point &operator*=(const T &v) & { x *= v; y *= v; return *this; } Point &operator/=(const T &v) & { x /= v; y /= v; return *this; } Point operator-() const { return Point(-x, -y); } friend Point operator+(Point a, const Point &b) { return a += b; } friend Point operator-(Point a, const Point &b) { return a -= b; } friend Point operator*(Point a, const T &b) { return a *= b; } friend Point operator/(Point a, const T &b) { return a /= b; } friend Point operator*(const T &a, Point b) { return b *= a; } // w/o tolerance // friend bool operator<(const Point &a, const Point &b) { // return a.x < b.x || (a.x == b.x && a.y < b.y); // } // w/ tolerance friend bool operator<(const Point &a, const Point &b) { return (a.x < b.x || (abs(a.x - b.x) < TOL && a.y < b.y)); } friend bool operator>(const Point &a, const Point &b) { return !(a < b); } // without tolerance // friend bool operator==(const Point &a, const Point &b) { // return a.x == b.x && a.y == b.y; // } // friend bool operator!=(const Point &a, const Point &b) { // return !(a.x == b.x && a.y == b.y); // } // with tolerance friend bool operator==(const Point &a, const Point &b) { Point<T> p = a - b; T len = sqrt(p.x * p.x + p.y * p.y); return len < TOL; } friend bool operator!=(const Point &a, const Point &b) { Point<T> p = a - b; T len = sqrt(p.x * p.x + p.y * p.y); return !(len < TOL); } friend std::istream &operator>>(std::istream &is, Point &p) { return is >> p.x >> p.y; } friend std::ostream &operator<<(std::ostream &os, const Point &p) { return os << "(" << p.x << ", " << p.y << ")"; } }; using Pt = Point<int>; int n, x, ya, yb, cur_x; vector<Pt> poly; map<int, int> y_ind; set<int> sweep, top_out; vector<ll> peri; void comp_peri() { for (int i = 0; i < n; i++) { peri[i] = abs(poly[(i + 1) % n].x - poly[i].x + poly[(i + 1) % n].y - poly[i].y); if (i) peri[i] += peri[i - 1]; } } void make_cw() { int lm = -1; for (int i = 0; i < n; i++) if (lm == -1 || poly[i] < poly[lm]) lm = i; if (poly[lm].y != poly[(lm + 1) % n].y) { rotate(poly.begin(), poly.begin() + (lm + 1) % n, poly.end()); reverse(poly.begin(), poly.end()); } else { rotate(poly.begin(), poly.begin() + lm, poly.end()); } } int right(int ind) { return poly[ind].y == poly[(ind + 1) % n].y ? (ind + 1) % n : (n + ind - 1) % n; } bool check(int p_ind, int q_ind, int extend) { Pt p, q, p_r, q_r; int c_x; p = poly[p_ind], q = poly[q_ind]; p_r = poly[right(p_ind)], q_r = poly[right(q_ind)]; ll c_peri, excess; if (p_ind > q_ind) { c_peri = peri[n - 1] - (p_ind ? peri[p_ind - 1] : 0); c_peri += (q_ind ? peri[q_ind - 1] : 0); } else { c_peri = peri[q_ind - 1] - (p_ind ? peri[p_ind - 1] : 0); } c_x = max(p.x, q.x); c_x += (peri[n - 1] / 2 - c_peri - p.x - q.x + 2 * c_x) / 2; if (c_x < cur_x) return false; if (c_x > min(p_r.x, q_r.x)) return false; if (!extend && c_x != cur_x) return false; vector<Pt> a, b; swap(p_ind, q_ind); int dp = 0, dq = 0; if (c_x == p.x) { b.push_back(p); } else if (c_x < p_r.x) { a.push_back(p); a.push_back(Pt(c_x, p.y)); b.push_back(Pt(c_x, p.y)); } else { a.push_back(p); a.push_back(Pt(c_x, p.y)); } if (c_x == q.x) { b.push_back(q); } else if (c_x < q_r.x) { a.push_back(q); a.push_back(Pt(c_x, q.y)); b.push_back(Pt(c_x, q.y)); } else { a.push_back(q); a.push_back(Pt(c_x, q.y)); } if (p_ind < q_ind) { for (int i = p_ind + 1; i < q_ind; i++) a.push_back(poly[i]); for (int i = q_ind + 1; i < n; i++) b.push_back(poly[i]); for (int i = 0; i < p_ind; i++) b.push_back(poly[i]); } else { for (int i = p_ind + 1; i < n; i++) a.push_back(poly[i]); for (int i = 0; i < q_ind; i++) a.push_back(poly[i]); for (int i = q_ind + 1; i < p_ind; i++) b.push_back(poly[i]); } if (a.size() != b.size()) return false; sort(a.begin(), a.end()); ll dx, dy; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { dx = dy = 2e9; if (i) for (int k = 0; k < b.size(); k++) b[k].x *= -1; if (j) for (int k = 0; k < b.size(); k++) b[k].y *= -1; sort(b.begin(), b.end()); for (int k = 0; k < b.size(); k++) { if (dx != 2e9 && dx != a[k].x - b[k].x) break; dx = a[k].x - b[k].x; if (dy != 2e9 && dy != a[k].y - b[k].y) break; dy = a[k].y - b[k].y; if (k == b.size() - 1) { x = c_x; ya = p.y; yb = q.y; return true; } } if (i) for (int k = 0; k < b.size(); k++) b[k].x *= -1; if (j) for (int k = 0; k < b.size(); k++) b[k].y *= -1; } } for (int k = 0; k < b.size(); k++) swap(b[k].x, b[k].y); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { dx = dy = 2e9; if (i) for (int k = 0; k < b.size(); k++) b[k].x *= -1; if (j) for (int k = 0; k < b.size(); k++) b[k].y *= -1; sort(b.begin(), b.end()); for (int k = 0; k < b.size(); k++) { if (dx != 2e9 && dx != a[k].x - b[k].x) break; dx = a[k].x - b[k].x; if (dy != 2e9 && dy != a[k].y - b[k].y) break; dy = a[k].y - b[k].y; if (k == b.size() - 1) { x = c_x; ya = p.y; yb = q.y; return true; } } if (i) for (int k = 0; k < b.size(); k++) b[k].x *= -1; if (j) for (int k = 0; k < b.size(); k++) b[k].y *= -1; } } return false; } bool extend(int y) { auto it = sweep.find(y); int p_ind, q_ind; int is_top = (top_out.find(y) != top_out.end()); if (is_top) { q_ind = y_ind[y]; p_ind = y_ind[*(--it)]; } else { p_ind = y_ind[y]; q_ind = y_ind[*(++it)]; } return check(p_ind, q_ind, 1); } bool is_vertical() { y_ind.clear(); sweep.clear(); top_out.clear(); cur_x = -1; make_cw(); comp_peri(); vector<pair<int, int>> to_sweep; for (int i = 0; i < n; i++) { if (poly[i].x == poly[(i + 1) % n].x) to_sweep.push_back(make_pair(i, (i + 1) % n)); } sort(to_sweep.begin(), to_sweep.end(), [&](const pair<int, int> &a, const pair<int, int> &b) { int x1 = poly[a.first].x, y1 = poly[a.first].y, x2 = poly[b.first].x, y2 = poly[b.first].y; return x1 < x2 || (x1 == x2 && y1 < y2); }); pair<int, int> p_ind, q_ind; Pt p, q, p_r, q_r; int prev = -1, type, ex; set<int>::iterator it; set<int> to_check; for (auto [p_ind, q_ind] : to_sweep) { p = poly[p_ind], q = poly[q_ind]; if (p.y > q.y) swap(p, q), swap(p_ind, q_ind); if (p.x != cur_x) { for (int y : to_check) { if (sweep.find(y) != sweep.end() && extend(y)) return true; } cur_x = p.x; to_check.clear(); prev = -1; } p_r = poly[right(p_ind)]; q_r = poly[right(q_ind)]; if (prev != -1) if (check(prev, p_ind, 0)) return true; prev = q_ind; type = ex = 0; if (p.x < p_r.x) { type ^= 1; sweep.insert(p.y); y_ind[p.y] = p_ind; to_check.insert(p.y); } else { sweep.erase(p.y); it = sweep.lower_bound(p.y); if (it != sweep.begin()) to_check.insert(*(--it)); } if (q.x < q_r.x) { type ^= 2; sweep.insert(q.y); y_ind[q.y] = q_ind; to_check.insert(q.y); } else { sweep.erase(q.y); it = sweep.lower_bound(q.y); if (it != sweep.end()) to_check.insert(*it); } if (type == 1) { if (top_out.find(q.y) != top_out.end()) { top_out.erase(q.y); top_out.insert(p.y); } } else if (type == 2) { if (top_out.find(p.y) != top_out.end()) { top_out.erase(p.y); top_out.insert(q.y); } } else if (type == 3) { it = sweep.find(p.y); if (it != sweep.begin() && top_out.find(*(--it)) == top_out.end()) top_out.insert(p.y); else top_out.insert(q.y); } } return false; } void solve() { cin >> n; poly.resize(n); peri.resize(n); for (int i = 0; i < n; i++) cin >> poly[i]; if (is_vertical()) { cout << x << " " << ya << " " << x << " " << yb << "\n"; } else { for (int i = 0; i < n; i++) swap(poly[i].x, poly[i].y); if (is_vertical()) { cout << ya << " " << x << " " << yb << " " << x << "\n"; } else cout << "NO\n"; } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); solve(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...