Submission #932686

#TimeUsernameProblemLanguageResultExecution timeMemory
932686Programmer123Fountain Parks (IOI21_parks)C++17
55 / 100
3550 ms131320 KiB
#ifndef LOCAL #pragma GCC optimize("Ofast") #pragma GCC target("avx2,sse4.2") #endif #include <bits/stdc++.h> #include "parks.h" std::unordered_map<int, int> map[100001]; int N; std::unordered_map<int, std::vector<int>> rely[100002]; std::vector<std::pair<int, int>> vld[200000]; std::pair<int, int> assigned[200000]; std::unordered_set<int> taken[100002]; time_t stop; std::default_random_engine Rand(std::random_device{}()); bool shuffle = false; bool Shuffle = false; bool doomed(int x) { for (auto a: vld[x]) if (!taken[a.first / 2].count(a.second)) return false; return true; } bool cantake(std::pair<int, int> a, int n) { for (auto x: rely[a.first / 2][a.second]) if (x > n && doomed(x)) return false; return true; } #ifdef LOCAL size_t called = 0; #endif bool backtrack(int n) { #ifdef LOCAL called++; #endif if (n == N - 1) return true; if (clock() > stop) return false; // if (Shuffle && vld[n].size() == 2 && Rand() % 2) { // std::swap(vld[n][0], vld[n][1]); // } for (auto a: vld[n]) { if (taken[a.first / 2].count(a.second)) continue; taken[a.first / 2].insert(a.second); if (!cantake(a, n)) { taken[a.first / 2].erase(a.second); continue; } if (backtrack(n + 1)) { assigned[n] = a; return true; } taken[a.first / 2].erase(a.second); } return false; } int construct_roads(std::vector<int> x, std::vector<int> y) { stop = clock() + 3.4 * CLOCKS_PER_SEC; N = (int) x.size(); if (N == 1) { build({}, {}, {}, {}); return 1; } int maxx = x[0]; int minx = x[0]; int maxy = y[0]; int miny = y[0]; for (int i = 0; i < N; ++i) { maxx = std::max(maxx, x[i]); minx = std::min(minx, x[i]); maxy = std::max(maxy, y[i]); miny = std::min(miny, y[i]); } for (int i = 0; i < N; ++i) { map[x[i] / 2][y[i]] = i; } while (true) { std::vector<int> u, v, a, b; bool seen[N]; for (int i = 0; i < N; ++i) { seen[i] = false; } std::queue<int> bfs; int start = 0; if (shuffle) { for (int i = 0; i < N; ++i) { if (x[i] < x[start]) start = i; if (x[i] == x[start] && y[i] < y[start]) start = i; } } if (Shuffle) { start = Rand() % N; } bfs.push(start); seen[start] = true; auto add = [&](int x, int y, std::vector<int> &data) { if (x < 0 || x > 200000) return; if (map[x / 2].count(y)) data.push_back(map[x / 2][y]); }; auto edges = [&](int x, int y) { std::vector<int> result; add(x, y + 2, result); add(x, y - 2, result); add(x + 2, y, result); add(x - 2, y, result); if (Shuffle) { std::shuffle(result.begin(), result.end(), Rand); } return result; }; int rem = N - 1; while (!bfs.empty()) { auto next = bfs.front(); bfs.pop(); for (auto n: edges(x[next], y[next])) { if (!seen[n]) { seen[n] = true; bfs.push(n); rem--; u.push_back(next); v.push_back(n); } } } if (rem) return 0; std::function<std::vector<std::pair<int, int>>(int, int)> valid = [&x, &y, minx, maxx, miny, maxy](int u, int v) -> std::vector<std::pair<int, int>> { if (x[u] == x[v]) { int _y = (y[u] + y[v]) / 2; if (x[u] == minx) return {{minx - 1, _y}}; if (x[u] == maxx) return {{maxx + 1, _y}}; return {{x[u] + 1, _y}, {x[u] - 1, _y}}; } else { int _x = (x[u] + x[v]) / 2; if (y[u] == miny) return {{_x, miny - 1}}; if (y[u] == maxy) return {{_x, maxy + 1}}; return {{_x, y[u] + 1}, {_x, y[u] - 1}}; } }; if (shuffle) { std::vector<std::pair<int, int>> Edges; for (int i = 0; i < N - 1; ++i) { Edges.emplace_back(u[i], v[i]); } std::sort(Edges.begin(), Edges.end(), [&](std::pair<int, int> a, std::pair<int, int> b) { int A = a.first; int B = b.first; if (x[A] == x[B]) return y[A] < y[B]; return x[A] < x[B]; }); for (int i = 0; i < N - 1; ++i) { u[i] = Edges[i].first; v[i] = Edges[i].second; } } for (int i = 0; i < N - 1; ++i) { vld[i] = valid(u[i], v[i]); if (Shuffle && vld[i].size() == 2 && Rand() % 2) { std::swap(vld[i][0], vld[i][1]); } } for (int i = 0; i < N - 1; ++i) { for (auto n: vld[i]) { rely[n.first / 2][n.second].push_back(i); } } if (backtrack(0)) { #ifdef LOCAL printf("Called backtrack %ld times.\n", called); called = 0; #endif for (int i = 0; i < N - 1; ++i) { a.push_back(assigned[i].first); b.push_back(assigned[i].second); } build(u, v, a, b); return 1; } #ifdef LOCAL printf("Called backtrack %ld times.\n", called); called = 0; #endif for (auto _x: x) { rely[(_x - 1) / 2].clear(); rely[(_x + 1) / 2].clear(); } Shuffle = shuffle; shuffle = true; if (clock() > stop) return 0; #ifdef LOCAL printf("Retrying...\n"); #endif } 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...