結果
問題 | No.96 圏外です。 |
ユーザー | KKT89 |
提出日時 | 2019-09-03 01:50:23 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,028 ms / 5,000 ms |
コード長 | 3,970 bytes |
コンパイル時間 | 1,391 ms |
コンパイル使用メモリ | 105,548 KB |
実行使用メモリ | 122,692 KB |
最終ジャッジ日時 | 2024-12-21 08:17:32 |
合計ジャッジ時間 | 9,741 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 91 ms
98,176 KB |
testcase_01 | AC | 91 ms
98,432 KB |
testcase_02 | AC | 91 ms
98,304 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 96 ms
98,688 KB |
testcase_05 | AC | 99 ms
99,200 KB |
testcase_06 | AC | 100 ms
99,328 KB |
testcase_07 | AC | 102 ms
99,896 KB |
testcase_08 | AC | 109 ms
100,544 KB |
testcase_09 | AC | 117 ms
101,500 KB |
testcase_10 | AC | 127 ms
102,504 KB |
testcase_11 | AC | 131 ms
103,656 KB |
testcase_12 | AC | 142 ms
104,704 KB |
testcase_13 | AC | 173 ms
107,032 KB |
testcase_14 | AC | 176 ms
108,808 KB |
testcase_15 | AC | 230 ms
111,488 KB |
testcase_16 | AC | 224 ms
114,052 KB |
testcase_17 | AC | 233 ms
116,200 KB |
testcase_18 | AC | 263 ms
117,516 KB |
testcase_19 | AC | 267 ms
117,384 KB |
testcase_20 | AC | 339 ms
119,600 KB |
testcase_21 | AC | 271 ms
121,724 KB |
testcase_22 | AC | 1,028 ms
122,692 KB |
testcase_23 | AC | 1,026 ms
122,692 KB |
testcase_24 | AC | 92 ms
98,176 KB |
testcase_25 | AC | 189 ms
110,712 KB |
testcase_26 | AC | 221 ms
114,512 KB |
testcase_27 | AC | 200 ms
112,240 KB |
ソースコード
#include <iostream> #include <algorithm> #include <vector> #include <numeric> #include <math.h> #include <complex> using namespace std; typedef long long int ll; typedef complex<long double> Point; typedef vector<Point> Polygon; // 多角形 const long double eps=1e-9; namespace std{ bool operator<(const Point &p,const Point &q){ if(p.real()<q.real()-eps) return true; if(p.real()>q.real()+eps) return false; return p.imag()<q.imag(); } } long double dot(Point a,Point b){ // 内積 return real(conj(a)*b); } long double cross(Point a,Point b){ // 外積 return imag(conj(a)*b); } //CCW int ccw(Point a,Point b,Point c){ b-=a; c-=a; if(cross(b,c)>eps){ return 1; // a,b,cが反時計回りの順に並ぶ } if(cross(b,c)<-eps){ return -1; // a,b,cが時計回りの順に並ぶ } if(dot(b,c)<0){ return 2; // c,a,bがこの順に一直線に並ぶ } if(norm(b)<norm(c)){ return -2; // a,b,cの順に一直線に並ぶ } return 0; // a,c,bの順に一直線に並ぶ } // 凸包:凸多角形のある一辺上にある点を含まない Polygon convex_hull(vector<Point> ps){ int n=(int)ps.size(); int k=0; // 凸包の頂点数 sort(ps.begin(),ps.end()); Polygon qs(2*n); // 構築中の凸包 for(int i=0;i<n;qs[k++]=ps[i++]){ while(k>=2&&ccw(qs[k-2],qs[k-1],ps[i])<=0) --k; } for(int i=n-2,t=k+1;i>=0;qs[k++]=ps[i--]){ while(k>=t&&ccw(qs[k-2],qs[k-1],ps[i])<=0) --k; } qs.resize(k-1); return qs; } // 凸多角形の直径 pair<pair<ll,ll>,long double> convex_diameter(const Polygon& poly){ int n=(int)poly.size(); if(n==2){ return make_pair(make_pair(0,1),abs(poly[0]-poly[1])); } int i=0,j=0; // ある方向に最も遠い点対 // x軸方向に最も遠い点対を求める for(int k=0;k<n;k++){ if(poly[k].imag()>poly[i].imag())i=k; if(poly[k].imag()<poly[j].imag())j=k; } pair<ll,ll> resp=make_pair(-1,-1); long double resd=0; int si,maxi,sj,maxj; si=maxi=i; sj=maxj=j; while(si!=maxj || sj!=maxi){ long double cur=abs(poly[si]-poly[sj]); if(resd+eps<cur){ resd=cur; resp=make_pair(si,sj); } int di=(si+1)%n, dj=(sj+1)%n; if(cross(poly[di]-poly[si],poly[dj]-poly[sj])<0){ si=di; } else{ sj=dj; } } return make_pair(resp,resd); } struct UnionFind{ vector<int> par,num; vector<bool> done; UnionFind(int n):par(n),num(n,1),done(n,false){ iota(par.begin(),par.end(),0); //include<numeric> } int find(int v){ return (par[v]==v)?v:(par[v]=find(par[v])); } void unite(int u,int v){ u=find(u),v=find(v); if(u==v)return; if(num[u]<num[v])swap(u,v); num[u]+=num[v]; par[v]=u; done[u]=done[u]|done[v]; } bool same(int u,int v){ return find(u) == find(v); } bool ispar(int v){ return v=find(v); } int size(int v){ return num[find(v)]; } }; int x[120010],y[120010]; int dx[9]={0,0,0,1,1,1,-1,-1,-1}; int dy[9]={0,1,-1,0,1,-1,0,1,-1}; int main(){ int n; cin >> n; if(n==0){ cout << 1 << endl; return 0; } Polygon ps; vector<vector<vector<ll> > > backet(2010,vector<vector<ll> >(2010)); for(int i=0;i<n;i++){ cin >> x[i] >> y[i]; ps.push_back(Point(x[i],y[i])); x[i]+=10000; y[i]+=10000; backet[x[i]/10][y[i]/10].push_back(i); } UnionFind uf(n); for(int i=0;i<2010;i++){ for(int j=0;j<2010;j++){ for(auto v:backet[i][j]){//近接するブロックを探索する for(int k=0;k<9;k++){ int ni=i+dx[k],nj=j+dy[k]; if(ni<0||nj<0)continue; for(auto vv:backet[ni][nj]){ if(v==vv)continue; if(abs(ps[v]-ps[vv])<10+eps){ uf.unite(v,vv); } } } } } } vector<Polygon> Polys(n); for(int i=0;i<n;i++){ Polys[uf.find(i)].push_back(ps[i]); } long double res=0; for(int i=0;i<n;i++){ if(Polys[i].size()<=1)continue; Polys[i]=convex_hull(Polys[i]); res=max(res,convex_diameter(Polys[i]).second); } res+=2; printf("%.10Lf\n",res); return 0; }