結果
問題 | No.96 圏外です。 |
ユーザー | koyumeishi |
提出日時 | 2014-12-09 04:50:59 |
言語 | C++11 (gcc 11.4.0) |
結果 |
AC
|
実行時間 | 603 ms / 5,000 ms |
コード長 | 8,738 bytes |
コンパイル時間 | 1,506 ms |
コンパイル使用メモリ | 114,204 KB |
実行使用メモリ | 24,692 KB |
最終ジャッジ日時 | 2024-06-06 15:52:55 |
合計ジャッジ時間 | 7,213 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 5 ms
5,376 KB |
testcase_05 | AC | 8 ms
5,376 KB |
testcase_06 | AC | 13 ms
5,376 KB |
testcase_07 | AC | 21 ms
5,376 KB |
testcase_08 | AC | 30 ms
6,016 KB |
testcase_09 | AC | 41 ms
7,032 KB |
testcase_10 | AC | 60 ms
7,660 KB |
testcase_11 | AC | 75 ms
9,704 KB |
testcase_12 | AC | 99 ms
11,580 KB |
testcase_13 | AC | 143 ms
11,272 KB |
testcase_14 | AC | 165 ms
14,836 KB |
testcase_15 | AC | 255 ms
14,456 KB |
testcase_16 | AC | 266 ms
19,412 KB |
testcase_17 | AC | 300 ms
24,692 KB |
testcase_18 | AC | 359 ms
22,668 KB |
testcase_19 | AC | 365 ms
22,672 KB |
testcase_20 | AC | 254 ms
16,404 KB |
testcase_21 | AC | 266 ms
15,276 KB |
testcase_22 | AC | 603 ms
16,784 KB |
testcase_23 | AC | 563 ms
16,660 KB |
testcase_24 | AC | 1 ms
5,376 KB |
testcase_25 | AC | 203 ms
18,568 KB |
testcase_26 | AC | 281 ms
22,872 KB |
testcase_27 | AC | 227 ms
20,308 KB |
ソースコード
#include <iostream> #include <vector> #include <cstdio> #include <sstream> #include <map> #include <string> #include <algorithm> #include <queue> #include <cmath> #include <set> using namespace std; #define EPS 1e-6 class xy{ public: double x; double y; xy(){ } xy(double xx, double yy){ x = xx; y = yy; } xy(const xy &v){ x = v.x; y = v.y; } xy& operator=(const xy &v){ x = v.x; y = v.y; return *this; } xy operator+(const xy &v) const{ return xy(this->x+v.x, this->y+v.y); } xy operator-(const xy &v) const{ return xy(this->x-v.x, this->y-v.y); } void operator+=(const xy &v){ x+=v.x; y+=v.y; } void operator-=(const xy &v){ x-=v.x; y-=v.y; } /* something wrong this operator for sorting bool operator<(const xy &v){ if(x!=v.x) return x < v.x; return y < v.y; } bool operator>(const xy &v){ if(x!=v.x) return x > v.x; return y > v.y; } */ }; //for sorting bool comp_xy(const xy &a, const xy &b){ if(a.x != b.x) return a.x < b.x; return a.y < b.y; } //u,v : vector O = (0,0) double cross(const xy &u, const xy &v){ return u.x*v.y - u.y*v.x; } //u,v : vector O = (0,0) double dot(const xy &u, const xy &v){ return u.x*v.x + u.y*v.y; } //distance between two points double dist_p_p(const xy &a, const xy &b){ return sqrt( fabs(dot(a-b, a-b)) ); } //distance between a point and a line segment double dist_p_ls(const xy &p, const xy &s1, const xy &s2){ xy vl = s2 - s1; xy vp = p - s1; return fabs( cross(vl, vp) / sqrt( dot(vl, vl) ) ); } //zero -> p1 int ccw(xy p1, xy p2, xy p3){ p2 -= p1; p3 -= p1; double c = cross(p2,p3); if( c > EPS /* c > 0 */) return +1; //counter-clockwise if( c < -EPS /* c < 0 */) return -1; //clock-wise if( dot(p2,p3) < -EPS) return +2; //on segment : p3-p1-p2 if( dot(p3,p3) < dot(p2,p2) +EPS ) return -2; //on segment : p1-p3-p2 return 0; } //segment p1-p2, p3-p4 bool inter_ss(xy p1, xy p2, xy p3, xy p4){ return ( (ccw(p1,p2, p3) * ccw(p1,p2, p4) <= 0) && (ccw(p3,p4, p1) * ccw(p3,p4, p2) <= 0 ) ) ; } //convex_hull vector<xy> convex_hull(vector<xy> &v){ sort( v.begin(), v.end(), comp_xy ); int k = 0; //nums of vertex vector<xy> tmp(v.size()*2); //conect i from k for(int i=0; i<v.size(); i++){ while(k>1 && cross (tmp[k-1] - tmp[k-2], v[i] - tmp[k-1]) <= 0 ) k--; tmp[k] = v[i]; k++; } for(int i=v.size()-2, t=k; i>=0; i--){ while(k>t && cross(tmp[k-1] - tmp[k-2], v[i] - tmp[k-1]) <= 0 ) k--; tmp[k] = v[i]; k++; } tmp.resize(k-1); return tmp; } pair<int, int> farthest_point_pair(vector<xy> &v /* v MUST BE CONVEX HULL*/){ int n = v.size(); int p = 0; //the point which has min y int q = 0; //the point which has max y for(int i=0; i<n; i++){ if( v[p].y > v[i].y ) p = i; if( v[q].y < v[i].y ) q = i; } double max_dist = dist_p_p( v[p], v[q] ); int ret_a = p; int ret_b = q; int s = p; int t = q; while(1){ if( cross( v[(s+1)%n]-v[s], v[(t+1)%n] - v[t] ) < 0 ) s = (s+1)%n; else t = (t+1)%n; if( dist_p_p( v[s], v[t] ) > max_dist ){ ret_a = s; ret_b = t; max_dist = dist_p_p( v[s], v[t] ); } if( s==p && t==q ) break; } return make_pair(ret_a, ret_b); } class UnionFindTree{ typedef struct { int parent; int rank; }base_node; vector<base_node> node; public: UnionFindTree(int n){ node.resize(n); for(int i=0; i<n; i++){ node[i].parent=i; node[i].rank=0; } } int find(int x){ if(node[x].parent == x) return x; else{ return node[x].parent = find(node[x].parent); } } bool same(int x, int y){ return find(x) == find(y); } void unite(int x, int y){ x = find(node[x].parent); y = find(node[y].parent); if(x==y) return; if(node[x].rank < node[y].rank){ node[x].parent = y; }else if(node[x].rank > node[y].rank){ node[y].parent = x; }else{ node[x].rank++; unite(x,y); } } }; template <class T> class kd_tree{ //node[i] covers left<= x <= right, bottom <= y <= right vector<T> left; vector<T> right; vector<T> top; vector<T> bottom; //number of nodes int n; //root of kd-tree int root; //node infomation < <x,y>, node number > vector<pair<pair<T,T>, int> > node; //node[i] covers node[j] such that cover[i].first <= j <= cover[i].second vector<pair<int,int> > cover; //node[i]'s child nodes. if child[i].first == -1 or child[i].second == -1 then node[i]'s left/right child is empty vector<pair<int,int> > child; //node[i] is divided by x axis then true, else false vector<bool> divided_by_x; //if x == true then this range [begin,end] will be divided by x axis, else by y axis int divide(bool x, int begin, int end){ //out of range if(begin > end || begin < 0 || end >= n){ return -1; } T l,r,t,b; if(x){ b = node[begin].first.second; t = node[end].first.second; }else{ l = node[begin].first.first; r = node[end].first.first; } if(begin != end){ if(x) sort(node.begin()+begin, node.begin()+end+1, kd_tree::comp_x); else sort(node.begin()+begin, node.begin()+end+1, kd_tree::comp_y); } int med = (begin+end+1)/2; if(x){ l = node[begin].first.first; r = node[end].first.first; }else{ b = node[begin].first.second; t = node[end].first.second; } left[med] = l; right[med] = r; top[med] = t; bottom[med] = b; cover[med] = make_pair(begin, end); divided_by_x[med] = x; child[med].first = child[med].second = -1; if(med-1 >= begin) child[med].first = divide(!x, begin, med-1); if(med+1 <= end) child[med].second = divide(!x, med+1, end); return med; } //find nodes in l <= x <= r, b <= y <= t void range_search(const T &l, const T &r, const T &b, const T &t, vector<int> &res, int pos){ if(pos<0) return; //all nodes are out of the range if(left[pos] > r || right[pos] < l || bottom[pos] > t || top[pos] < b) return; //all nodes are in the range if(l<= left[pos] && right[pos] <= r && b <= bottom[pos] && top[pos] <= t){ for(int i=cover[pos].first; i<=cover[pos].second; i++){ res.push_back(node[i].second); } return; } //some nodes are in the range T x = node[pos].first.first; T y = node[pos].first.second; //node[pos] is contained if(l<=x && x<=r && b<=y && y<=t) res.push_back(node[pos].second); //about pos's child range_search(l,r,b,t, res, child[pos].first); range_search(l,r,b,t, res, child[pos].second); } public: static bool comp_x(const pair<pair<T,T>, int> &a, const pair<pair<T,T>, int> &b) { return a.first.first < b.first.first; } static bool comp_y(const pair<pair<T,T>, int> &a, const pair<pair<T,T>, int> &b) { return a.first.second < b.first.second; } //node infomation < <x,y>, node number > kd_tree(vector< pair<pair<T,T>, int> > v){ node = v; n = node.size(); left.resize(n); right.resize(n); top.resize(n); bottom.resize(n); cover.resize(n); child.resize(n); divided_by_x.resize(n); sort(node.begin(), node.end(), kd_tree::comp_y); root = divide(true, 0, n-1); } void range_search(const T &l, const T &r, const T &b, const T &t, vector<int> &res){ range_search(l,r,b,t, res, root); } }; bool check(xy &a, xy &b){ return dist_p_p(a,b) <= 10; } int main(){ int n; cin >> n; vector<pair<pair<int,int>, int> > v(n); vector<xy> q(n); for(int i=0; i<n; i++){ int x,y; cin >> x >> y; v[i] = make_pair(make_pair(x,y), i); q[i] = xy(x,y); } UnionFindTree uft(n); kd_tree<int> kdt(v); for(int i=0; i<n; i++){ vector<int> candidate; int x = v[i].first.first; int y = v[i].first.second; kdt.range_search(x-10, x+10, y-10, y+10, candidate); for(int j=0; j<candidate.size(); j++){ if(candidate[j] == i) continue; if(check(q[i], q[ candidate[j] ])){ uft.unite(i, candidate[j]); } } } map<int, vector<xy> > S; for(int i=0; i<n; i++){ int par = uft.find(i); if(S.find(par) != S.end()){ S[par].push_back( q[i] ); }else{ S[par] = vector<xy>(0); S[par].push_back( q[i] ); } } double ans = 1.0; for(auto itr = S.begin(); itr != S.end(); itr++){ if(itr->second.size() == 1){ ans = max(ans, 2.0); continue; } vector<xy> hull = convex_hull( itr->second ); pair<int,int> d = farthest_point_pair(hull); double tmp = dist_p_p( hull[d.first], hull[d.second] ) + 2.0; ans = max(ans, tmp); } printf("%.7f\n", ans); return 0; }