旋转卡壳

Graham

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<bits/stdc++.h>
using namespace std;
int n;
int chosen[500001];
struct point {
double x,y;
}p[500001];
double cross(point a,point b,point c,point d)
{
return (b.x-a.x)*(d.y-c.y)-(d.x-c.x)*(b.y-a.y);
}
double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dis_power(point a,point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp1(point a,point b)
{
return a.y<b.y;
}
bool cmp2(point a,point b)
{
double ans=cross(p[1],a,p[1],b);
if(ans>0)
{
return 1;
}
if(ans==0)
{
return dis(p[0],a)<dis(p[0],b);
}
return 0;
}
int main()
{
cin>>n;
if(n==1)
{
cout<<"0.00"<<endl;
}
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
sort(p+1,p+n+1,cmp1);
sort(p+2,p+n+1,cmp2);
int tot=0;
chosen[++tot]=1;
for(int i=2;i<=n;i++)
{
while(tot>=2&&(cross(p[chosen[tot-1]],p[chosen[tot]],p[chosen[tot]],p[i])<0))
{
tot--;
}
chosen[++tot]=i;
}
chosen[++tot]=1;
double maxs=0;
int maxi;
for(int i=2;i<tot;i++)
{
if(p[chosen[i]].y>maxs)
{
maxs=p[chosen[i]].y;
maxi=i;
}
}
int j=maxi;
double ans=0;
for(int i=1;i<tot;i++)
{
while(dis(p[chosen[i]],p[chosen[j]])>dis(p[chosen[i]],p[chosen[j-1]]))
{
j++;
}
j--;
ans=max(ans,dis_power(p[chosen[i]],p[chosen[j]]));
}
printf("%.0lf",ans);
return 0;
}