結果
| 問題 |
No.96 圏外です。
|
| コンテスト | |
| ユーザー |
assy1028
|
| 提出日時 | 2016-12-16 01:26:18 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,620 bytes |
| コンパイル時間 | 1,578 ms |
| コンパイル使用メモリ | 128,700 KB |
| 実行使用メモリ | 44,340 KB |
| 最終ジャッジ日時 | 2024-11-30 09:42:52 |
| 合計ジャッジ時間 | 40,123 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 27 TLE * 1 |
ソースコード
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <map>
#include <numeric>
#include <cmath>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <complex>
#include <string.h>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <iomanip>
#include <sys/time.h>
#include <random>
using namespace std;
#define endl '\n'
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define UNIQ(v) (v).erase(unique((v).begin(), (v).end()), (v).end())
typedef long long ll;
struct pairhash {
public:
template<typename T, typename U>
size_t operator()(const pair<T, U> &x) const {
size_t seed = hash<T>()(x.first);
return hash<U>()(x.second) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
};
const ll mod = 1e9 + 7;
const double pi = acos(-1);
typedef long double D;
typedef complex<D> P;
typedef vector<P> Poly, ConvexPoly;
const D inf = 1e12, eps = 1e-10;
#define X real()
#define Y imag()
int sig(D a, D b=0) {return a < b-eps ? -1 : (a > b+eps ? 1 : 0);}
template<typename T> bool eq(const T& a, const T& b) {return sig(abs(a-b)) == 0;}
bool compX(const P& a, const P& b) {return !eq(a.X, b.X) ? sig(a.X, b.X) < 0 : sig(a.Y, b.Y) < 0;}
namespace std {
bool operator < (const P& a, const P& b) {return compX(a, b);}
bool operator == (const P& a, const P& b) {return eq(a,b);}
};
D cross(const P& a, const P& b) {return imag(conj(a) * b);}
D dot(const P& a, const P& b) {return real(conj(a) * b);}
int ccw(const P& a, P b, P c) {
b -= a; c -= a;
if (sig(cross(b, c)) > 0) return 1; //counter clockwise
if (sig(cross(b, c)) < 0) return -1; //clockwise
if (sig(dot(b, c)) < 0) return 2; //c--a--b on line
if (sig(norm(b), norm(c))) return -2; //a--b--c on line
return 0; //a--c--b on line
}
// 凸包
// O(n logn)
ConvexPoly convex_hull(Poly& ps) {
int n = ps.size(), k = 0;
sort(ALL(ps));
Poly ch(2*n);
for (int i = 0; i < n; i++) {
while (k > 1 && cross(ch[k-1]-ch[k-2], ps[i]-ch[k-1]) < 0) k--;
ch[k++] = ps[i];
}
for (int i = n-2, t = k; i >= 0; i--) {
while (k > t && cross(ch[k-1]-ch[k-2], ps[i]-ch[k-1]) < 0) k--;
ch[k++] = ps[i];
}
ch.resize(k-1);
return ch;
}
// 凸多角形の直径
// O(n)
D convex_diameter(const ConvexPoly& ps) {
const int l = ps.size();
int is = 0, js = 0;
for (int i = 0; i < l; i++) if (ps[i].Y > ps[is].Y) is = i;
for (int j = 0; j < l; j++) if (ps[j].Y < ps[js].Y) js = j;
D maxd = abs(ps[is] - ps[js]);
int i = is, maxi = is, j = js, maxj = js;
do {
if (cross(ps[(i+1)%l]-ps[i], ps[(j+1)%l]-ps[j]) >= 0) j = (j+1)%l;
else i = (i+1)%l;
D dis = abs(ps[i]-ps[j]);
if (dis > maxd) {
maxd = dis;
maxi = i;
maxj = j;
}
} while (i != js || j != is);
return maxd;
// farthest pair is (maxi, maxj).
}
D area2(const Poly& ps) {
D res = 0;
int n = ps.size();
for (int i = 0; i < n; i++)
res += cross(ps[i], ps[(i+1)%n]);
return res;
}
class UnionFind {
private:
static const int MAX = 120010;
int par[MAX];
int r[MAX];
public:
UnionFind(int n = MAX) {
for (int i = 0; i < n; i++) {
par[i] = i;
r[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 (r[x] < r[y]) {
par[x] = y;
} else {
par[y] = x;
if (r[x] == r[y]) r[x]++;
}
}
bool same(int x, int y) {
return find(x) == find(y);
}
};
int n;
pair<int, int> xy[120010];
P p[120010];
Poly g[120010];
D dist(D x0, D y0, D x1, D y1) {
return sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
}
D solve() {
if (n == 0) return 1.0;
map<pair<int, int>, int> memo;
for (int i = 0; i < n; i++) memo[xy[i]] = i;
vector<pair<int, int> > vec;
for (int dy = -10; dy <= 10; dy++) {
for (int dx = -10; dx <= 10; dx++) {
if (!(dx==0&&dy==0) && dist(0, 0, dx, dy) < 10.0+eps)
vec.push_back(make_pair(dx, dy));
}
}
UnionFind uf(n);
int l = vec.size();
for (int i = 0; i < n; i++) {
for (int j = 0; j < l; j++) {
pair<int, int> XY = make_pair(xy[i].first+vec[j].first, xy[i].second+vec[j].second);
if (memo.count(XY) > 0) {
uf.unite(i, memo[XY]);
}
}
}
set<int> s;
for (int i = 0; i < n; i++) {
int v = uf.find(i);
s.insert(v);
g[v].push_back(p[i]);
}
D res = 2.0;
for (int v : s) {
int k = g[v].size();
if (k == 2) res = max(res, 2.0+dist(g[v][0].X, g[v][0].Y, g[v][1].X, g[v][1].Y));
else if (k > 2) {
ConvexPoly cp = convex_hull(g[v]);
if (area2(cp) < eps) {
res = max(res, 2.0+dist(g[v][0].X, g[v][0].Y, g[v][k-1].X, g[v][k-1].Y));
} else {
res = max(res, 2.0+convex_diameter(cp));
}
}
}
return res;
}
void input() {
cin >> n;
int x, y;
for (int i = 0; i < n; i++) {
cin >> x >> y;
xy[i] = make_pair(x, y);
p[i] = P(x, y);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout << fixed << setprecision(15);
input();
cout << solve() << endl;
}
assy1028