結果

問題 No.96 圏外です。
ユーザー motxxmotxx
提出日時 2014-12-09 03:50:49
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 1,481 ms / 5,000 ms
コード長 4,588 bytes
コンパイル時間 1,694 ms
コンパイル使用メモリ 162,636 KB
実行使用メモリ 22,512 KB
最終ジャッジ日時 2023-08-25 21:34:06
合計ジャッジ時間 9,306 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 4 ms
7,712 KB
testcase_01 AC 3 ms
7,844 KB
testcase_02 AC 3 ms
7,828 KB
testcase_03 AC 3 ms
7,512 KB
testcase_04 AC 7 ms
8,160 KB
testcase_05 AC 9 ms
8,268 KB
testcase_06 AC 13 ms
8,596 KB
testcase_07 AC 21 ms
8,568 KB
testcase_08 AC 25 ms
9,280 KB
testcase_09 AC 35 ms
9,944 KB
testcase_10 AC 72 ms
10,720 KB
testcase_11 AC 67 ms
11,632 KB
testcase_12 AC 64 ms
13,108 KB
testcase_13 AC 230 ms
13,412 KB
testcase_14 AC 168 ms
15,316 KB
testcase_15 AC 482 ms
15,896 KB
testcase_16 AC 290 ms
18,348 KB
testcase_17 AC 205 ms
22,184 KB
testcase_18 AC 398 ms
20,736 KB
testcase_19 AC 398 ms
20,672 KB
testcase_20 AC 345 ms
20,408 KB
testcase_21 AC 172 ms
21,016 KB
testcase_22 AC 1,481 ms
22,444 KB
testcase_23 AC 1,441 ms
22,512 KB
testcase_24 AC 4 ms
7,704 KB
testcase_25 AC 141 ms
18,148 KB
testcase_26 AC 191 ms
20,920 KB
testcase_27 AC 159 ms
19,076 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#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 = 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;
}
0