[HNOI2008]水平可见直线 半平面交
求向直线们的俯视视角中可见的直线,以为是选最大最小斜率然后往中间放。。其实就是半平面交
//#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int maxn=5e4+7; const double eps=1e-6; struct Line{ double a,b;int id; }l[maxn]; bool cmp(Line l1,Line l2){ if(fabs(l1.a-l2.a)<eps)return l1.b<l2.b; return l1.a<l2.a; } Line st[maxn];bool ans[maxn]; int top,n; double crossx(Line l1,Line l2){ //解出l1,l2交点横坐标 return (l2.b-l1.b)/(l1.a-l2.a); } void insert(Line a){ while(top){ if(fabs(st[top].a-a.a)<eps)top--; //保留较高直线 else if(top>1 && crossx(a,st[top-1])<=crossx(st[top],st[top-1])) top--; else break; } st[++top]=a; } void work(){ for(int i=1;i<=n;i++)insert(l[i]); for(int i=1;i<=top;i++)ans[st[i].id]=1; for(int i=1;i<=n;i++) if(ans[i])printf("%d ",i); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf",&l[i].a,&l[i].b); l[i].id=i; } sort(l+1,l+n+1,cmp); work(); }