题目描述
Description
艾泽拉斯世界经历一场亘古未有的地震过后,大地和海洋被完全撕裂,旧大陆残缺不全。联盟和部落各种族的居民们被迫离开了世代居住的家园,来寻找新的生存空间。原本平坦的陆地上现在隆起了一座座山峰,暴风城的人类开始在艾尔文山脉重建家园。他们决定在山脉之中建造一座瞭望塔和一个魔法浮空岛,以便于在瞭望塔和浮空岛上可以俯视艾尔文山脉的全貌。
艾尔文山脉被描述为一个折线,给定每个点的坐标(横纵坐标均不小于0),按照横坐标从小到大顺次连接起来就是就是山脉的折线。折线上所有点的横坐标均不相同。如果一个位置与山脉任何一点的连线均不被挡住(但可以与地面相切),那么就说这一点可以望到整个艾尔文山脉。瞭望塔的塔身不会挡住视线,而且瞭望塔和浮空岛可以建造在同一位置。为节省建筑材料,瞭望塔塔身的高度必须尽量小,即从塔顶到塔底的距离尽量小,瞭望塔可以建在山坡上。由于气候因素,浮空岛应建立在海拔尽量低的位置(甚至可以建在地面上),海平面高度为0。如果有多个位置均满足条件,则选择横坐标最小的那个。瞭望塔和浮空岛横坐标范围应在艾尔文山脉横坐标范围之内。
给定艾尔文山脉,请你求出瞭望塔和浮空岛的位置。
Input
第1行,一个整数N,表示描述艾尔文山脉的折线的顶点数。
第2-N+1行,每行两个整数,xi,yi表示折线上点的坐标。
Output
第1行,两个保留2位小数的浮点数x1,y1,表示瞭望塔顶端的坐标。
第2行,两个保留2位小数的浮点数x2,y2,表示浮空岛的坐标。
Sample Input
6
2 2
6 1
8 6
10 3
16 5
20 2
Sample Output
8.00 11.00
9.54 9.85
Data Constraint
Hint
【样例说明】 样例中描述的艾尔文山脉各个顶点,按照横坐标顺序顺次连接后的折线如下图所示:
瞭望塔应建造在山峰(8,6)处,塔顶端为(8,11),高度为5,此时瞭望塔的高度最小。
浮空岛建立在(9.54,9.85)处,海拔高度最低。
【数据规模】
40%的数据2<=N<=10
100%的数据2<=N<=1 000 000;
0<=xi,yi<=5 000 000
题解
半平面交裸题
而且只有下凸壳所以不用队列
浮空岛就是凸壳最低点
瞭望塔的x只可能是下凸壳/原点中的某个x
加上凸壳的首尾两个点,排序后单调找,每次找相邻的一类点中间的其它点来求交
然鹅
本题的坑点在于时间/空间/精度
自己感受
上面两个是同一个程序
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define cj(a,b,c) ((c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y))
#define abs(x) ((x)>0?(x):-(x))
#define max(a,b) (a>b?a:b)
#define pi 3.14159265358979323846
#define E 0.0000001
using namespace std;
struct P{
double x,y;
P (double _x=0,double _y=0) {x=_x,y=_y;}
} O=P(0,0),p[100001],Jd,A[1000001];
struct P2{
double x,y;
int type;
} b[2000001];
struct L{
P s1,s2;
float xl;
L (double _x1=0,double _y1=0,double _x2=0,double _y2=0) {s1.x=_x1,s1.y=_y1,s2.x=_x2,s2.y=_y2;}
} a[1000001],l1,l2; //s1-->s2
int N,n,i,j,k,l,t,tot,ls1,ls2;
double ans1,ans1x,ans1y,ans2,ans2x,ans2y,s;
long double s1,s2,S;
char ch[16000001];
char *Ch=ch;
int getint()
{
int x=0;
while (*Ch<'0' || *Ch>'9' ) *++Ch;
while (*Ch>='0' && *Ch<='9') x=x*10+(*Ch-'0'),*++Ch;
return x;
}
//long double cj(P a,P b,P c)
//{
// long double s=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);
//
// if (abs(s)<=E)
// return 0;
// else
// return s;
//}
bool cmp(L a,L b)
{
return abs(a.xl-b.xl)>E && a.xl<b.xl || abs(a.xl-b.xl)<=E && cj(a.s1,a.s2,b.s2)<0;
}
bool Cmp(P2 a,P2 b)
{
return a.x<b.x;
}
bool CMP(P a,P b)
{
return a.x<b.x;
}
P jd(L a,L b)
{
s1=cj(a.s1,b.s1,a.s2),s2=cj(a.s1,a.s2,b.s2);
S=s1/(s1+s2);
return P(b.s1.x+(b.s2.x-b.s1.x)*S,b.s1.y+(b.s2.y-b.s1.y)*S);
}
float xl(L a)
{
float x=a.s2.x-a.s1.x,y=a.s2.y-a.s1.y;
if (abs(y)<=E)
{
if (x>0)
return 0;
else
return pi;
}
if (abs(x)<=E)
{
if (y>0)
return pi/2;
else
return pi*3/2;
}
if (x>0 && y>0)
return atan(y/x);
if (x<0 && y>0)
return atan(y/x)+pi;
if (x<0 && y<0)
return atan(y/x)+pi;
if (x>0 && y<0)
return atan(y/x)+pi+pi;
}
int main()
{
// freopen("cataclysm38.in","r",stdin);
// freopen("S8_2_3.in","r",stdin);
fread(ch,1,16000001,stdin);
n=getint();
fo(i,1,n)
A[i].x=getint(),A[i].y=getint();
sort(A+1,A+n+1,CMP);
N=0;
fo(i,2,n)
{
++N;
a[N]=L(A[i].x,A[i].y,A[i-1].x,A[i-1].y);
a[N].xl=xl(a[N]);
}
sort(a+1,a+N+1,cmp);
j=0;
fo(i,1,N)
if (i==1 || abs(a[i].xl-a[i-1].xl)>E)
a[++j]=a[i];
N=j;
t=1;
fo(i,2,N)
{
while (t>1 && cj(a[i].s1,a[i].s2,p[t-1])<=0)
--t;
a[++t]=a[i];
p[t-1]=jd(a[t-1],a[t]);
}
tot=0;
fo(i,1,n)
{
++tot;
b[tot].x=A[i].x;
b[tot].y=A[i].y;
b[tot].type=0;
}
fo(i,1,t-1)
{
++tot;
b[tot].x=p[i].x;
b[tot].y=p[i].y;
b[tot].type=1;
}
if (t==1 || p[1].x>A[1].x)
{
++tot;
l1=L(A[1].x,A[1].y,A[1].x,233333333333333ll);
Jd=jd(l1,a[1]);
b[tot].x=Jd.x;
b[tot].y=Jd.y;
b[tot].type=1;
}
if (t==1 || p[t-1].x<A[n].x)
{
++tot;
l1=L(A[n].x,A[n].y,A[n].x,233333333333333ll);
Jd=jd(l1,a[t]);
b[tot].x=Jd.x;
b[tot].y=Jd.y;
b[tot].type=1;
}
sort(b+1,b+tot+1,Cmp);
ans1=233333333333333ll;
ans2=233333333333333ll;
ls1=0;
ls2=0;
fo(i,1,tot)
{
if (i<tot && abs(b[i].x-b[i+1].x)<=E)
{
s=abs(b[i].y-b[i+1].y);
if (abs(s-ans1)>E && s<ans1 || abs(s-ans1)<=E && b[i].x<ans1x)
{
ans1=s;
ans1x=b[i].x;
ans1y=max(b[i].y,b[i+1].y);
}
}
if (!b[i].type)
{
if (ls1)
{
fo(j,ls1+1,i-1)
{
// l1=L(b[j].x,-233333333333333ll,b[j].x,b[j].y);
// l2=L(b[ls1].x,b[ls1].y,b[i].x,b[i].y);
//
// Jd=jd(l1,l2);
Jd.x=b[j].x;
Jd.y=b[ls1].y+(b[j].x-b[ls1].x)/(b[i].x-b[ls1].x)*(b[i].y-b[ls1].y);
s=b[j].y-Jd.y;
if (abs(s-ans1)>E && s<ans1 || abs(s-ans1)<=E && b[j].x<ans1x)
{
ans1=s;
ans1x=b[j].x;
ans1y=b[j].y;
}
}
}
ls1=i;
}
else
{
if (ls2)
{
fo(j,ls2+1,i-1)
{
// l1=L(b[j].x,233333333333333ll,b[j].x,b[j].y);
// l2=L(b[ls2].x,b[ls2].y,b[i].x,b[i].y);
//
// Jd=jd(l1,l2);
Jd.x=b[j].x;
Jd.y=b[ls2].y+(b[j].x-b[ls2].x)/(b[i].x-b[ls2].x)*(b[i].y-b[ls2].y);
s=Jd.y-b[j].y;
if (abs(s-ans1)>E && s<ans1 || abs(s-ans1)<=E && Jd.x<ans1x)
{
ans1=s;
ans1x=Jd.x;
ans1y=Jd.y;
}
}
}
ls2=i;
s=b[i].y;
if (abs(s-ans2)>E && s<ans2 || abs(s-ans2)<=E && b[i].x<ans2x)
{
ans2=s;
ans2x=b[i].x;
ans2y=b[i].y;
}
}
}
if (abs(ans1x)<=E) ans1x=0;
if (abs(ans1y)<=E) ans1y=0;
if (abs(ans2x)<=E) ans2x=0;
if (abs(ans2y)<=E) ans2y=0;
printf("%0.2lf %0.2lf\n",ans1x,ans1y);
printf("%0.2lf %0.2lf\n",ans2x,ans2y);
}