結果

問題 No.96 圏外です。
ユーザー motxxmotxx
提出日時 2014-12-09 03:48:54
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 2,751 ms / 5,000 ms
コード長 4,589 bytes
コンパイル時間 1,659 ms
コンパイル使用メモリ 162,612 KB
実行使用メモリ 19,340 KB
最終ジャッジ日時 2023-08-25 21:33:21
合計ジャッジ時間 15,879 ms
ジャッジサーバーID
(参考情報)
judge15 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 3 ms
4,688 KB
testcase_01 AC 2 ms
4,656 KB
testcase_02 AC 2 ms
4,672 KB
testcase_03 AC 2 ms
4,380 KB
testcase_04 AC 6 ms
4,868 KB
testcase_05 AC 8 ms
5,204 KB
testcase_06 AC 13 ms
5,248 KB
testcase_07 AC 33 ms
5,520 KB
testcase_08 AC 31 ms
6,112 KB
testcase_09 AC 47 ms
6,572 KB
testcase_10 AC 160 ms
7,108 KB
testcase_11 AC 105 ms
8,400 KB
testcase_12 AC 77 ms
9,408 KB
testcase_13 AC 638 ms
10,132 KB
testcase_14 AC 327 ms
12,032 KB
testcase_15 AC 1,481 ms
12,620 KB
testcase_16 AC 669 ms
15,132 KB
testcase_17 AC 275 ms
17,840 KB
testcase_18 AC 984 ms
17,176 KB
testcase_19 AC 980 ms
17,184 KB
testcase_20 AC 517 ms
17,240 KB
testcase_21 AC 196 ms
17,504 KB
testcase_22 AC 2,751 ms
19,228 KB
testcase_23 AC 2,654 ms
19,340 KB
testcase_24 AC 2 ms
4,608 KB
testcase_25 AC 173 ms
14,076 KB
testcase_26 AC 246 ms
16,760 KB
testcase_27 AC 199 ms
14,804 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 = 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;
}
0