結果
問題 | No.2652 [Cherry 6th Tune N] Δρονε χιρχλινγ |
ユーザー | umimel |
提出日時 | 2024-02-23 23:01:33 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 13,841 bytes |
コンパイル時間 | 3,219 ms |
コンパイル使用メモリ | 228,672 KB |
実行使用メモリ | 22,516 KB |
最終ジャッジ日時 | 2024-09-29 08:19:00 |
合計ジャッジ時間 | 23,076 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
10,624 KB |
testcase_01 | AC | 1,513 ms
5,248 KB |
testcase_02 | AC | 1,522 ms
6,820 KB |
testcase_03 | AC | 1,610 ms
6,820 KB |
testcase_04 | TLE | - |
testcase_05 | TLE | - |
testcase_06 | TLE | - |
testcase_07 | TLE | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
testcase_28 | -- | - |
testcase_29 | -- | - |
testcase_30 | -- | - |
testcase_31 | -- | - |
testcase_32 | -- | - |
testcase_33 | -- | - |
testcase_34 | -- | - |
testcase_35 | -- | - |
testcase_36 | -- | - |
testcase_37 | -- | - |
testcase_38 | -- | - |
testcase_39 | -- | - |
testcase_40 | -- | - |
testcase_41 | -- | - |
コンパイルメッセージ
main.cpp: In function 'void solve()': main.cpp:411:18: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17' [-Wc++17-extensions] 411 | for(auto [dist, u, v] : E){ | ^
ソースコード
#include<bits/stdc++.h> using namespace std; using ll = long long; using pll = pair<ll, ll>; #define drep(i, cc, n) for (ll i = (cc); i <= (n); ++i) #define rep(i, n) drep(i, 0, n - 1) #define all(a) (a).begin(), (a).end() #define pb push_back #define fi first #define se second mt19937_64 rng(chrono::system_clock::now().time_since_epoch().count()); const ll MOD1000000007 = 1000000007; const ll MOD998244353 = 998244353; const ll MOD[3] = {999727999, 1070777777, 1000000007}; const ll LINF = 1LL << 60LL; const int IINF = (1 << 30) - 1; struct union_find{ vector<int> par; vector<int> siz; union_find(int n) : par(n), siz(n, 1){ for(int i=0; i<n; i++) par[i] = i; } int root(int x){ if (par[x] == x) return x; return par[x] = root(par[x]); } void unite(int x, int y){ int rx = root(x); int ry = root(y); if (rx == ry) return; if (siz[rx] < siz[ry]) swap(rx, ry); siz[rx] += siz[ry]; par[ry] = rx; } bool same(int x, int y){ int rx = root(x); int ry = root(y); return rx == ry; } int size(int x){ return siz[root(x)]; } }; template<typename T> struct edge{ int from, to; T cost; edge(){} edge(int to, T cost = 1) : from(-1), to(to), cost(cost){} edge(int from, int to, T cost) : from(from), to(to), cost(cost){} }; template<typename T> struct redge{ int from, to; T cap, cost; int rev; redge(int to, T cap, T cost=(T)(1)) : from(-1), to(to), cap(cap), cost(cost){} redge(int to, T cap, T cost, int rev) : from(-1), to(to), cap(cap), cost(cost), rev(rev){} }; template<typename T> using Edges = vector<edge<T>>; template<typename T> using weighted_graph = vector<Edges<T>>; template<typename T> using tree = vector<Edges<T>>; using unweighted_graph = vector<vector<int>>; template<typename T> using residual_graph = vector<vector<redge<T>>>; namespace delaunay { struct Point { /*** Point on the 2D-plane ***/ double x, y; Point operator + (const Point& p) const { return Point{x + p.x, y + p.y}; } Point operator - (const Point& p) const { return Point{x - p.x, y - p.y}; } Point operator * (double d) const { return Point{x * d, y * d}; } Point operator / (double d) const { return Point{x / d, y / d}; } bool operator < (const Point& p) const { return x == p.x ? y < p.y : x < p.x; } Point normal() const { return Point{y, -x}; } double norm() const { return x * x + y * y; } }; double dot(Point a, Point b) { return a.x * b.x + a.y * b.y; } double cross(Point a, Point b) { return a.x * b.y - a.y * b.x; } /*** Edge connecting two points ***/ using Edge = std::pair<size_t, size_t>; Edge make_edge(size_t a, size_t b) { return Edge(std::min(a,b), std::max(a,b)); } /*** Core Implementation ***/ class DelaunayTriangulation { bool is_ccw(size_t a, size_t b, size_t c) const { return cross(P[b] - P[a], P[c] - P[a]) > 0; } struct Triangle { /*** Triangle on the 2D-plane ***/ size_t a, b, c; size_t opposite(Edge e) const { if (e.first != a and e.second != a) return a; if (e.first != b and e.second != b) return b; return c; } }; Triangle make_triangle(size_t a, size_t b, size_t c) const { /*** Make triangle where the direction 'a->b->c' is counter-clockwise ***/ if (!is_ccw(a, b, c)) std::swap(b, c); return Triangle{a, b, c}; } bool point_in_triangle(size_t tar, const Triangle& t) const { /*** Check wheter a point lies in an triangle or not ***/ if (!is_ccw(t.a, t.b, tar)) return false; if (!is_ccw(t.b, t.c, tar)) return false; if (!is_ccw(t.c, t.a, tar)) return false; return true; } private: size_t n; std::vector<Point> P; std::vector<Triangle> T; std::vector<std::list<size_t>> CH; std::vector<Edge> edge; size_t add_child_triangle(size_t k, const Triangle& t) { /*** Add a child triangle for T[k] ***/ size_t new_k = T.size(); T.push_back(t); CH.push_back(std::list<size_t>()); CH[k].push_back(new_k); return new_k; } size_t add_child_triangle(size_t k1, size_t k2, const Triangle& t) { /*** Add a child triangle for T[k1] and T[k2] ***/ size_t new_k = T.size(); T.push_back(t); CH.push_back(std::list<size_t>()); CH[k1].push_back(new_k); CH[k2].push_back(new_k); return new_k; } size_t find_child(size_t k, size_t tar) const { /*** Find child triangle of T[k] where P[tar] lies in ***/ for (size_t i : CH[k]) if (point_in_triangle(tar, T[i])) return i; return std::numeric_limits<size_t>::max(); } private: struct EdgeHash { /*** Hash function for edges ***/ size_t operator () (const Edge& e) const { static const size_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); size_t key = ((e.first << 16) ^ e.second) ^ FIXED_RANDOM; return key ^ (key >> 16); } }; // Maps an edge to its incident triangles std::unordered_map<Edge, std::set<size_t>, EdgeHash> e2t; void register_triangle(size_t k, const Triangle& t) { /*** Register a new triangle ***/ e2t[make_edge(t.a, t.b)].insert(k); e2t[make_edge(t.b, t.c)].insert(k); e2t[make_edge(t.c, t.a)].insert(k); } void unregister_triangle(size_t k, const Triangle& t) { /*** Unregister an old triangle ***/ e2t[make_edge(t.a, t.b)].erase(k); e2t[make_edge(t.b, t.c)].erase(k); e2t[make_edge(t.c, t.a)].erase(k); } private: bool is_ilegal(Edge e, size_t c, size_t tar) { /*** Check wheter an edge is ilegal or not ***/ size_t a = e.first, b = e.second; Point s1 = (P[a] + P[b]) / 2.; Point s2 = (P[b] + P[c]) / 2.; Point t1 = s1 + (P[b] - P[a]).normal(); Point t2 = s2 + (P[c] - P[b]).normal(); double d1 = cross(t2 - s2, s2 - s1); double d2 = cross(t2 - s2, t1 - s1); Point ct = s1 + (t1 - s1) * d1 / d2; double dx1 = P[a].x - ct.x; double dy1 = P[a].y - ct.y; double dx2 = P[tar].x - ct.x; double dy2 = P[tar].y - ct.y; return (dx1 * dx1 + dy1 * dy1) > (dx2 * dx2 + dy2 * dy2); } void legalize_edge(size_t piv, Edge e) { /*** Legalize an edge with pivot P[piv] ***/ if (e2t.count(e) == 0) return; if (e2t[e].size() != 2) return; size_t k1 = *e2t[e].begin(); size_t k2 = *e2t[e].rbegin(); size_t a = T[k1].opposite(e); size_t b = T[k2].opposite(e); if (is_ilegal(e, a, b)) { unregister_triangle(k1, T[k1]); unregister_triangle(k2, T[k2]); e2t.erase(e); Triangle t1 = make_triangle(e.first, a, b); Triangle t2 = make_triangle(e.second, a, b); size_t k1_ = add_child_triangle(k1, k2, t1); size_t k2_ = add_child_triangle(k1, k2, t2); register_triangle(k1_, t1); register_triangle(k2_, t2); size_t c = (piv != a ? a : b); legalize_edge(piv, make_edge(e.first, c)); legalize_edge(piv, make_edge(e.second, c)); } } void sub_division(size_t k, size_t tar) { /*** Divide triangle T[k] by P[tar] ***/ unregister_triangle(k, T[k]); Triangle t1 = make_triangle(T[k].a, T[k].b, tar); Triangle t2 = make_triangle(T[k].b, T[k].c, tar); Triangle t3 = make_triangle(T[k].c, T[k].a, tar); size_t k1 = add_child_triangle(k, t1); size_t k2 = add_child_triangle(k, t2); size_t k3 = add_child_triangle(k, t3); register_triangle(k1, t1); register_triangle(k2, t2); register_triangle(k3, t3); legalize_edge(tar, make_edge(T[k].a, T[k].b)); legalize_edge(tar, make_edge(T[k].b, T[k].c)); legalize_edge(tar, make_edge(T[k].c, T[k].a)); } void modify_convexity() { /*** Modify edges of the bounding convex hull ***/ for (size_t a=n; a<=n+2; ++a) { for (size_t b=0; b<n; ++b) { Edge e(b, a); if (e2t.count(e) == 0) continue; size_t k1 = *e2t[e].begin(); size_t k2 = *e2t[e].rbegin(); size_t c = T[k1].opposite(e); size_t d = T[k2].opposite(e); if (!is_ccw(a, b, c)) std::swap(c, d); if (!is_ccw(c, d, b)) continue; unregister_triangle(k1, T[k1]); unregister_triangle(k2, T[k2]); Triangle t1 = make_triangle(a, c, d); Triangle t2 = make_triangle(b, c, d); size_t k1_ = add_child_triangle(k1, k2, t1); size_t k2_ = add_child_triangle(k1, k2, t2); register_triangle(k1_, t1); register_triangle(k2_, t2); } } } private: std::uint32_t seed; std::uint32_t xor128() { static std::uint32_t x = seed, y = 362436069, z = 521288629, w = 88675123; std::uint32_t t = (x ^ (x << 11)); x = y; y = z; z = w; return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8))); } public: DelaunayTriangulation(const std::vector<double>& x, const std::vector<double>& y, uint32_t seed_ = 123456789) { n = x.size(); P = std::vector<Point>(n); for (size_t i=0; i<n; ++i) { P[i].x = x[i]; P[i].y = y[i]; } double r = std::numeric_limits<double>::min(); for (size_t i=0; i<n; ++i) { r = std::max(r, std::abs(P[i].x)); r = std::max(r, std::abs(P[i].y)); } // Add three vertices of the initial bounding triangle P.push_back(Point{3.1 * r, 0}); P.push_back(Point{0, 3.1 * r}); P.push_back(Point{-3.1 * r, -3.1 * r}); seed = seed_; } void execute(double min_delta = 1e-6, double max_delta = 1e-5, int max_miss_count = 30) { /*** Execute the algorithm ***/ // Random reordering std::vector<size_t> id(n); std::iota(id.begin(), id.end(), size_t(0)); for (size_t i=0; i<n; ++i) { size_t j = xor128() % (n - i); std::swap(id[j], id[n - i - 1]); } // Initialize each data structure T = std::vector<Triangle>(); CH = std::vector<std::list<size_t>>(); T.push_back(make_triangle(n, n+1, n+2)); CH.push_back(std::list<size_t>()); register_triangle(0, T[0]); e2t = std::unordered_map<Edge, std::set<size_t>, EdgeHash>(); // Main iteration for (size_t tar : id) { int miss_count = 0; double px = P[tar].x, py = P[tar].y; size_t k = 0; while (!CH[k].empty()) { size_t nxt = find_child(k, tar); if (nxt == std::numeric_limits<size_t>::max()) { ++miss_count; if (miss_count >= max_miss_count) break; // P[tar] perturbates when it falls on an edge double dx = min_delta + (max_delta - min_delta) * xor128() / 0xFFFFFFFFu; double dy = min_delta + (max_delta - min_delta) * xor128() / 0xFFFFFFFFu; dx *= (xor128() % 2 == 0 ? 1 : -1); dy *= (xor128() % 2 == 0 ? 1 : -1); P[tar].x = px + dx; P[tar].y = py + dy; } else { k = nxt; } } if (CH[k].empty()) sub_division(k, tar); P[tar].x = px; P[tar].y = py; } // Modify edges of the bounding convex hull modify_convexity(); // Save the solution edge = std::vector<Edge>(); for (auto it : e2t) { Edge e = it.first; if (e.first < n and e.second < n) edge.push_back(e); } } const std::vector<Edge>& get_edges() { return edge; } void dump(std::ostream& os) { os << edge.size() << std::endl; for (Edge e : edge) os << e.first << " " << e.second << std::endl; } }; } void solve(){ int n, l; cin >> n >> l; vector<double> x(n), y(n); for(int i=0; i<n; i++) cin >> x[i] >> y[i]; delaunay::DelaunayTriangulation DT(x, y); DT.execute(); vector<delaunay::Edge> tmp_E = DT.get_edges(); vector<tuple<int, int, int>> E; for(int i=0; i<(int)tmp_E.size(); i++){ int u = tmp_E[i].first; int v = tmp_E[i].second; int dist = abs(x[u]-x[v])+abs(y[u]-y[v]); E.pb({dist, u, v}); } sort(all(E)); union_find uf(n); tree<int> T(n); for(auto [dist, u, v] : E){ if(!uf.same(u, v)){ uf.unite(u, v); T[u].pb(edge<int>(v)); T[v].pb(edge<int>(u)); } } vector<int> ans; function<void(int, int)> dfs = [&](int v, int p){ ans.pb(v); for(edge<int> e : T[v]) if(e.to!=p){ dfs(e.to, v); } }; dfs(0, -1); cout << n << '\n'; for(int i=0; i<n; i++) cout << (ll)x[ans[i]] << " " << (ll)y[ans[i]] << '\n'; } int main(){ cin.tie(nullptr); ios::sync_with_stdio(false); int T=1; cin >> T; while(T--) solve(); }