結果
問題 | No.96 圏外です。 |
ユーザー | motxx |
提出日時 | 2014-12-09 03:48:54 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 2,217 ms / 5,000 ms |
コード長 | 4,589 bytes |
コンパイル時間 | 1,666 ms |
コンパイル使用メモリ | 175,604 KB |
実行使用メモリ | 19,508 KB |
最終ジャッジ日時 | 2024-06-06 15:51:36 |
合計ジャッジ時間 | 12,889 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 5 ms
5,376 KB |
testcase_05 | AC | 8 ms
5,376 KB |
testcase_06 | AC | 11 ms
5,632 KB |
testcase_07 | AC | 30 ms
5,760 KB |
testcase_08 | AC | 30 ms
6,272 KB |
testcase_09 | AC | 43 ms
6,872 KB |
testcase_10 | AC | 140 ms
7,508 KB |
testcase_11 | AC | 93 ms
8,400 KB |
testcase_12 | AC | 72 ms
9,808 KB |
testcase_13 | AC | 552 ms
10,324 KB |
testcase_14 | AC | 283 ms
11,988 KB |
testcase_15 | AC | 1,199 ms
12,780 KB |
testcase_16 | AC | 558 ms
15,188 KB |
testcase_17 | AC | 249 ms
17,744 KB |
testcase_18 | AC | 824 ms
17,496 KB |
testcase_19 | AC | 818 ms
17,492 KB |
testcase_20 | AC | 428 ms
17,348 KB |
testcase_21 | AC | 168 ms
17,624 KB |
testcase_22 | AC | 2,094 ms
19,508 KB |
testcase_23 | AC | 2,217 ms
19,384 KB |
testcase_24 | AC | 2 ms
5,376 KB |
testcase_25 | AC | 162 ms
14,036 KB |
testcase_26 | AC | 225 ms
16,720 KB |
testcase_27 | AC | 183 ms
14,928 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; #define REP(i,a,b) for(int i=a;i<(int)b;i++) #define rep(i,n) REP(i,0,n) typedef double Real; // typedef long double Real; typedef complex<Real> P; namespace std { bool operator < (P const& a, P const& b) { return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b); } } Real dot(P const& a, P const& b) { return real(conj(a)*b); } Real cross(P const& a, P const& b) { return imag(conj(a)*b); } enum { counter_clockwise=+1, clockwise=-1, cab_online=+2, abc_online=-2, on_segment = 0 }; int ccw(P a, P b, P c) { b -= a; c -= a; if(cross(b, c) > 0) return counter_clockwise; if(cross(b, c) < 0) return clockwise; if(dot(b, c) < 0) return cab_online; if(norm(b) < norm(c)) return abc_online; return on_segment; } typedef vector<P> Polygon; #define prev(G, i) ( G[(i-1 + G.size()) % G.size()] ) #define curr(G, i) ( G[i % G.size()] ) #define next(G, i) ( G[(i+1) % G.size()] ) Polygon convex_hull(vector<P> ps) { int n = ps.size(), k = 0; sort(ps.begin(), ps.end()); vector<P> ch(2*n); for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull while (k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; for (int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]) // upper-hull while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; ch.resize(k-1); return ch; } Real convex_naive_diameter(Polygon const& g) { int N = g.size(); Real ret = 0.; rep(i, N) REP(j, i, N) { ret = max(ret, abs(g[i]-g[j])); } return ret; } #define diff(G, i) (next(G, i) - curr(G, i)) // 対蹠点対のみを走査して O(n) キャリバー法 Real convex_diameter(Polygon const& g) { int const N = g.size(); int is = 0, js = 0; REP(i, 1, N) { if(imag(g[i]) > imag(g[is])) { is = i; } if(imag(g[i]) < imag(g[js])) { js = i; } } Real mxd = norm(g[is]-g[js]); int i, mxi, j, mxj; i = mxi = is; j = mxj = js; do { if(cross(diff(g, i), diff(g, j)) >= 0) { j = (j+1) % N; } else { i = (i+1) % N; } if(norm(g[i]-g[j]) > mxd) { mxd = norm(g[i]-g[j]); mxi = i, mxj = j; } } while(i != is || mxj != js); return mxd; } inline bool inrange(int x, int y, int W, int H) { return 0<=x&&x<W&&0<=y&&y<H; } struct UnionFind { vector<int> rank; vector<int> par; UnionFind(int n) { rank.resize(n), par.resize(n); rep(i, n) { par[i] = i; rank[i] = 0; } } int find(int x) { if(par[x] == x) { return x; } else { return par[x] = find(par[x]); } } void unite(int x, int y) { x = find(x), y = find(y); if(x == y) { return; } if(rank[x] < rank[y]) { par[x] = y; } else { par[y] = x; if(rank[x] == rank[y]) { rank[x] ++; } } } bool same(int x, int y) { return find(x) == find(y); } }; vector<P> ps; int constexpr Offset = 10000; int constexpr MaxSize = 21000; int constexpr BSize = 100; vector<int> bucket[MaxSize/BSize][MaxSize/BSize]; int main() { int N; cin >> N; if(N == 0) { cout << 1 << endl; return 0; } //if(N == 1) { cout << 10 << endl; return 0; } rep(i, N) { double x, y; cin >> x >> y; //cerr << x << ", " << y << " " << Offset << endl; ps.push_back(P(x+Offset, y+Offset)); } /* if(N == 2) { if(abs(ps[0]-ps[1]) <= 10.) { cerr << ps[0] << " " << ps[1] << endl; cerr << abs(ps[0]-ps[1]) << endl; printf("%.10f\n", abs(ps[0]-ps[1])+10); return 0; } } */ rep(i, N) { int bx = ps[i].real()/BSize; int by = ps[i].imag()/BSize; bucket[by][bx].push_back(i); } UnionFind uf(2*N); rep(i, N) { int bx = ps[i].real()/BSize; int by = ps[i].imag()/BSize; REP(outy, -1, 2) REP(outx, -1, 2) { int x = bx+outx, y = by+outy; if(inrange(x, y, MaxSize/BSize, MaxSize/BSize)) { for(auto j: bucket[y][x]) { //cerr << "bucket: " << x << ", "<< y << endl; //cerr << "ps: " << i << ", " << j << endl; if(abs(ps[i]-ps[j]) <= 10.) { uf.unite(i, j); } } } } } vector<vector<P> > clusters(N); rep(i, N) { clusters[uf.find(i)].push_back(ps[i]); } Real ans = 0.; for(auto& g: clusters) { if(g.empty()) { continue; } //Real dia = convex_diameter(g); g = convex_hull(g); Real dia = convex_naive_diameter(g); ans = max(ans, dia+2); } printf("%.10f\n", ans); return 0; }