結果
問題 | No.96 圏外です。 |
ユーザー |
![]() |
提出日時 | 2014-12-09 03:50:49 |
言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
結果 |
AC
|
実行時間 | 1,262 ms / 5,000 ms |
コード長 | 4,588 bytes |
コンパイル時間 | 1,924 ms |
コンパイル使用メモリ | 177,288 KB |
実行使用メモリ | 22,480 KB |
最終ジャッジ日時 | 2024-12-24 08:01:29 |
合計ジャッジ時間 | 8,414 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 28 |
ソースコード
#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-hullwhile (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-hullwhile (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 = 50;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;}