当前位置: 代码迷 >> 综合 >> 【HNOI2008】bzoj1007 水平可见直线
  详细解决方案

【HNOI2008】bzoj1007 水平可见直线

热度:34   发布时间:2024-01-13 10:17:25.0

半平面交简化版。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=500010;
const double eps=1e-8;
int cmp(double x)
{if (x>=eps) return 1;if (fabs(x)<=eps) return 0;return -1;
}
struct Vector
{double x,y;Vector operator + (const Vector &v) const{return (Vector){
   x+v.x,y+v.y};}Vector operator - (const Vector &v) const{return (Vector){
   x-v.x,y-v.y};}Vector operator * (const double &k) const{return (Vector){
   x*k,y*k};}
}p[maxn];
typedef Vector Point;
double dot(Vector v,Vector u)
{return v.x*u.x+v.y*u.y;
}
double cross(Vector v,Vector u)
{return v.x*u.y-v.y*u.x;
}
struct Line
{Point p;Vector v;int id;/*double angle() const{return atan2(v.y,v.x);}*/bool operator < (const Line &l) const{return cmp(v.y-l.v.y)==-1;}
}a[maxn],q[maxn];
Point intersection(Line l,Line m)
{Vector u=l.p-m.p;double t=cross(m.v,u)/cross(l.v,m.v);return l.p+l.v*t;
}
int n,ans[maxn];
int main()
{//freopen("e.in","r",stdin);//freopen("e.out","w",stdout);//freopen("bzoj_1007.in","r",stdin);//freopen("bzoj_1007.out","w",stdout);int hd,tl;double x,y;scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%lf%lf",&x,&y);a[i]=(Line){(Point){
   0,y},(Vector){
   1,x},i};}sort(a+1,a+n+1);q[hd=tl=1]=a[1];for (int i=2;i<=n;i++){while (hd<tl&&cmp(cross(a[i].v,p[tl-1]-a[i].p))<=0) tl--;//while (hd<tl&&cmp(cross(a[i].v,p[hd]-a[i].p))<=0) hd++;if (q[tl]<a[i]) q[++tl]=a[i];else if (cmp(cross(a[i].v,q[tl].p-a[i].p))<=0) q[tl]=a[i];if (hd<tl) p[tl-1]=intersection(q[tl-1],q[tl]);}//while (hd<tl-1&&cmp(cross(q[1].v,p[tl-1]-q[1].p))<=0) tl--;for (int i=hd;i<=tl;i++) ans[q[i].id]=1;for (int i=1;i<=n;i++)if (ans[i]) printf("%d ",i);
}