結果
問題 | No.96 圏外です。 |
ユーザー | なお |
提出日時 | 2014-12-07 19:35:04 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 250 ms / 5,000 ms |
コード長 | 4,220 bytes |
コンパイル時間 | 1,823 ms |
コンパイル使用メモリ | 180,980 KB |
実行使用メモリ | 114,432 KB |
最終ジャッジ日時 | 2024-06-06 15:34:28 |
合計ジャッジ時間 | 6,839 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 72 ms
97,404 KB |
testcase_01 | AC | 73 ms
97,408 KB |
testcase_02 | AC | 71 ms
97,408 KB |
testcase_03 | AC | 72 ms
97,152 KB |
testcase_04 | AC | 75 ms
97,744 KB |
testcase_05 | AC | 78 ms
98,048 KB |
testcase_06 | AC | 80 ms
98,432 KB |
testcase_07 | AC | 84 ms
98,816 KB |
testcase_08 | AC | 89 ms
99,584 KB |
testcase_09 | AC | 96 ms
100,316 KB |
testcase_10 | AC | 103 ms
100,552 KB |
testcase_11 | AC | 115 ms
102,372 KB |
testcase_12 | AC | 128 ms
104,028 KB |
testcase_13 | AC | 141 ms
102,464 KB |
testcase_14 | AC | 159 ms
106,004 KB |
testcase_15 | AC | 186 ms
103,648 KB |
testcase_16 | AC | 213 ms
109,152 KB |
testcase_17 | AC | 235 ms
114,432 KB |
testcase_18 | AC | 250 ms
111,104 KB |
testcase_19 | AC | 244 ms
110,976 KB |
testcase_20 | AC | 189 ms
102,184 KB |
testcase_21 | AC | 194 ms
103,132 KB |
testcase_22 | AC | 212 ms
100,872 KB |
testcase_23 | AC | 214 ms
100,876 KB |
testcase_24 | AC | 72 ms
97,408 KB |
testcase_25 | AC | 186 ms
109,444 KB |
testcase_26 | AC | 219 ms
112,896 KB |
testcase_27 | AC | 195 ms
110,856 KB |
ソースコード
// 想定解法: バケット + Union-Find + 凸包 // 計算量: O(NlogN) // 参考 // http://www-ikn.ist.hokudai.ac.jp/~k-sekine/slides/convexhull.pdf // http://www.prefield.com/algorithm/geometry/convex_hull.html // http://www.prefield.com/algorithm/geometry/ccw.html // http://www.prefield.com/algorithm/geometry/convex_diameter.html #include <bits/stdc++.h> using namespace std; void rc(int v,int mn,int mx){if(v<mn||mx<v){cerr<<"error"<<endl;exit(1);}} #define ITER(c) __typeof__((c).begin()) #define FOREACH(it, c) for (ITER(c) it=(c).begin(); it != (c).end(); ++it) #define REP(i, n) for(int(i)=0;(i)<(n);++(i)) #define FOR(i, f, t) for(int(i)=(f);(i)<(t);(++i)) typedef complex<int> P; const int MAXN = 120000, MINXY = -10000, MAXXY = +10000; const int RANGE = 10*10; int N, X[MAXN+1], Y[MAXN+1]; int norm(int i,int j){int x=X[i]-X[j],y=Y[i]-Y[j];return x*x+y*y;} class uf_ { public: vector<int> node; uf_(int n) : node(n, -1){;} void con(int n, int m){ n = root(n); m = root(m); if(n == m) return; node[n] += node[m]; node[m] = n; } bool is_con(int n, int m){ return root(n) == root(m); } int root(int n){ return (node[n] < 0) ? n : node[n] = root(node[n]); } int size(int n){ return -node[root(n)]; } }; int inprd(const P &a, const P &b){ return (conj(a) * b).real(); } int outprd(const P &a, const P &b){ return (conj(a) * b).imag(); } // http://www.prefield.com/algorithm/geometry/ccw.html int ccw(int i, int j, int k) { P a(X[i],Y[i]),b(X[j],Y[j]),c(X[k],Y[k]); b -= a; c -= a; if(outprd(b, c) > 0) return +1; // counter clockwise if(outprd(b, c) < 0) return -1; // clockwise if(inprd(b, c) < 0) return +2; // c--a--b on line if(norm(b) < norm(c)) return -2; // a--b--c on line return 0; } // http://www.prefield.com/algorithm/geometry/convex_hull.html vector<int> convex_hull(vector<int> ps) { int n = ps.size(), k = 0; if(n < 3) return ps; sort(ps.begin(), ps.end(), [](int i, int j){ return ((X[i]!=X[j])?(X[i]<X[j]):(Y[i]<Y[j])); }); vector<int> ch(2*n); // lower-hull for(int i = 0; i < n; ch[k++] = ps[i++]){ while(k >= 2 && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; } // upper-hull for(int i = n-2, t = k+1; i >= 0; ch[k++] = ps[i--]){ while(k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k; } ch.resize(k-1); return ch; } vector<int> v[(MAXXY-MINXY)/10+1][(MAXXY-MINXY)/10+1]; int main(){ //freopen("in/05.txt", "r", stdin); // input : O(N) cin >> N; rc(N, 0, MAXN); REP(i, N){ cin >> X[i] >> Y[i]; rc(X[i], MINXY, MAXXY); rc(Y[i], MINXY, MAXXY); v[(Y[i]-MINXY)/10][(X[i]-MINXY)/10].push_back(i); } if(N == 0){ cout << 1 << endl; return 0; } uf_ uf(N); // O(N*900) REP(i,N){ int dx = (X[i]-MINXY)/10; int dy = (Y[i]-MINXY)/10; for(int y = -1; y <= 1; y++){ if(dy+y < 0 || dy+y > (MAXXY-MINXY)/10) continue; for(int x = -1; x <= 1; x++){ if(dx+x < 0 || dx+x > (MAXXY-MINXY)/10) continue; for(auto &j : v[dy+y][dx+x]){ if(i == j) continue; if(norm(i,j) <= RANGE) uf.con(i,j); } } } } // 点集合を各クラスタに分割: O(NlogN) map<int, vector<int> > m; REP(i,N) m[uf.root(i)].push_back(i); // クラスタ毎に凸包を取って最遠点対を求める map<int,int> stat; int maxr = 0; for(auto &it : m){ auto ch = convex_hull(it.second); int n = ch.size(); stat[n]++; // このへんまでで最大でも N=1300 程度まで落ちるので O(N^2) REP(i,n) REP(j,n){ if(i == j) continue; maxr = max(maxr, norm(ch[i],ch[j])); } } for(auto &v : stat) cerr << v.first << ":" << v.second << "/"; cerr<<endl; cout << fixed << setprecision(16) << sqrt((double)maxr)+2.0 << endl; return 0; }