Submission #414575

#TimeUsernameProblemLanguageResultExecution timeMemory
414575usachevd0Hamburg Steak (JOI20_hamburg)C++17
100 / 100
704 ms66184 KiB
#include <bits/stdc++.h> using namespace std; #define fi first #define se second #define mp make_pair #define pb push_back #define all(a) (a).begin(), (a).end() #define Time (clock() * 1.0 / CLOCKS_PER_SEC) using ll = long long; using ull = unsigned long long; using pii = pair<int, int>; using pil = pair<int, ll>; using pli = pair<ll, int>; using pll = pair<ll, ll>; using ld = long double; template<typename T1, typename T2> bool chkmin(T1& x, T2 y) { return y < x ? (x = y, true) : false; } template<typename T1, typename T2> bool chkmax(T1& x, T2 y) { return y > x ? (x = y, true) : false; } void debug_out() { cerr << endl; } template<typename T1, typename... T2> void debug_out(T1 A, T2... B) { cerr << ' ' << A; debug_out(B...); } template<typename T> void mdebug_out(T* a, int n) { for (int i = 0; i < n; ++i) cerr << a[i] << ' '; cerr << endl; } #ifdef LOCAL #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) #define mdebug(a, n) cerr << #a << ": ", mdebug_out(a, n) #else #define debug(...) 1337 #define mdebug(a, n) 1337 #endif template<typename T> ostream& operator << (ostream& stream, const vector<T>& v) { for (auto& x : v) stream << x << ' '; return stream; } template<typename T1, typename T2> ostream& operator << (ostream& stream, const pair<T1, T2>& p) { return stream << p.first << ' ' << p.second; } const int INF32 = 1e9; using Point = array<int, 2>; using Segm = Point; Segm universe_segm; Segm intersect(const Segm& s1, const Segm& s2) { return {max(s1[0], s2[0]), min(s1[1], s2[1])}; } void uintersect(Segm& s1, const Segm& s2) { chkmax(s1[0], s2[0]); chkmin(s1[1], s2[1]); } bool in(int x, const Segm& s) { return s[0] <= x && x <= s[1]; } bool empt(const Segm& s) { return s[0] > s[1]; } struct Rect { Segm s[2]; Rect() {} void read() { cin >> s[0][0] >> s[1][0] >> s[0][1] >> s[1][1]; } bool in(Point P) { return ::in(P[0], s[0]) && ::in(P[1], s[1]); } } universe_rect; ostream& operator << (ostream& stream, const Rect& r) { return stream << r.s[0][0] << ' ' << r.s[1][0] << ' ' << r.s[0][1] << ' ' << r.s[1][1]; } Rect intersect(const Rect& r1, const Rect& r2) { Rect r3; for (int a = 0; a < 2; ++a) { r3.s[a][0] = max(r1.s[a][0], r2.s[a][0]); r3.s[a][1] = min(r1.s[a][1], r2.s[a][1]); } return r3; } vector<Point> solve(int k, vector<Rect> rects, vector<Point> points) { if (rects.empty()) { while (k--) points.push_back({0, 0}); return points; } Rect I = universe_rect; for (Rect& r : rects) I = intersect(I, r); if (k == 1) { if (I.s[0][0] > I.s[0][1] || I.s[1][0] > I.s[1][1]) { return {}; } else { points.push_back({I.s[0][0], I.s[1][0]}); return points; } } for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { Point P{I.s[0][i], I.s[1][j]}; points.push_back(P); vector<Rect> new_rects; for (auto r : rects) if (!r.in(P)) new_rects.push_back(r); auto res = solve(k - 1, new_rects, points); if (!res.empty()) { return res; } points.pop_back(); } } return {}; } int32_t main() { #ifdef LOCAL freopen("in", "r", stdin); #endif ios::sync_with_stdio(0); cin.tie(0); universe_rect.s[0][0] = universe_rect.s[1][0] = 0; universe_rect.s[0][1] = universe_rect.s[1][1] = +INF32; universe_segm = {0, +INF32}; int n, k; cin >> n >> k; vector<int> rv; vector<Rect> rects(n); for (auto& r : rects) { r.read(); for (int a = 0; a < 2; ++a) for (int b = 0; b < 2; ++b) rv.push_back(r.s[a][b]); } sort(all(rv)); rv.resize(unique(all(rv)) - rv.begin()); int X = rv.size(); for (auto& r : rects) for (int a = 0; a < 2; ++a) { assert(r.s[a][0] <= r.s[a][1]); for (int b = 0; b < 2; ++b) r.s[a][b] = lower_bound(all(rv), r.s[a][b]) - rv.begin(); assert(r.s[a][0] <= r.s[a][1]); } auto easy = solve(k, rects, {}); if (!easy.empty()) { for (auto P : easy) cout << rv[P[0]] << ' ' << rv[P[1]] << '\n'; exit(0); } assert(k == 4); Rect I = universe_rect; for (Rect r : rects) I = intersect(I, r); int R = I.s[0][0], L = I.s[0][1]; int U = I.s[1][0], D = I.s[1][1]; assert(L < R); assert(D < U); Segm baseL = {D + 1, U - 1}; Segm baseR = {D + 1, U - 1}; Segm baseD = {L + 1, R - 1}; Segm baseU = {L + 1, R - 1}; vector<Segm> prefLR(X + 1, universe_segm); vector<Segm> suffLR(X + 1, universe_segm); vector<Segm> prefDU(X + 1, universe_segm); // also prefUD vector<Segm> prefLU(X + 1, universe_segm); vector<Segm> suffLD(X + 1, universe_segm); vector<Segm> prefUR(X + 1, universe_segm); vector<Segm> prefDR(X + 1, universe_segm); int minxUD = +INF32; for (Rect r : rects) { Segm rx = r.s[0], ry = r.s[1]; int touchL = in(L, rx); int touchR = in(R, rx); int touchD = in(D, ry); int touchU = in(U, ry); int sum = touchL + touchR + touchD + touchU; if (sum == 0) throw; if (sum >= 3) continue; if (sum == 1) { if (touchL) { uintersect(baseL, ry); } else if (touchR) { uintersect(baseR, ry); } else if (touchD) { uintersect(baseD, rx); } else { // touchU uintersect(baseU, rx); } } else { // sum = 2 if (touchL && touchR) { uintersect(prefLR[ry[0]], ry); uintersect(suffLR[ry[1] + 1], ry); } else if (touchD && touchU) { chkmin(minxUD, rx[1]); uintersect(prefDU[rx[0]], rx); } else if (touchL && touchU) { uintersect(prefLU[ry[0]], rx); } else if (touchL && touchD) { uintersect(suffLD[ry[1] + 1], rx); } else if (touchU && touchR) { uintersect(prefUR[rx[0]], ry); } else if (touchD && touchR) { uintersect(prefDR[rx[0]], ry); } } } for (int x = 0; x < X; ++x) { uintersect(suffLR[x + 1], suffLR[x]); uintersect(suffLD[x + 1], suffLD[x]); } for (int x = X - 1; x >= 0; --x) { uintersect(prefLR[x], prefLR[x + 1]); uintersect(prefDU[x], prefDU[x + 1]); uintersect(prefLU[x], prefLU[x + 1]); uintersect(prefUR[x], prefUR[x + 1]); uintersect(prefDR[x], prefDR[x + 1]); } for (int l = baseL[0]; l <= baseL[1]; ++l) { for (int rotUD = 0; rotUD < 2; ++rotUD) { auto segmU = intersect(baseU, prefLU[l + 1]); auto segmD = intersect(baseD, suffLD[l]); auto segmR = intersect(intersect(baseR, prefLR[l + 1]), suffLR[l]); int d, u; if (rotUD == 0) { // U <= D u = min(segmU[1], minxUD); if (u < segmU[0]) continue; uintersect(segmD, prefDU[u + 1]); uintersect(segmR, prefUR[u + 1]); if (empt(segmD)) continue; d = segmD[1]; if (d < u) continue; uintersect(segmR, prefDR[d + 1]); } else { // U >= D d = min(segmD[1], minxUD); if (d < segmD[0]) continue; uintersect(segmU, prefDU[d + 1]); uintersect(segmR, prefDR[d + 1]); if (empt(segmU)) continue; u = segmU[1]; if (u < d) continue; uintersect(segmR, prefUR[u + 1]); } if (empt(segmR)) continue; int r = segmR[1]; cout << rv[L] << ' ' << rv[l] << '\n'; cout << rv[R] << ' ' << rv[r] << '\n'; cout << rv[d] << ' ' << rv[D] << '\n'; cout << rv[u] << ' ' << rv[U] << '\n'; exit(0); } } throw; 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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...