bzoj1007: [HNOI2008]水平可见直线

来源:互联网 发布:svm算法代码 编辑:程序博客网 时间:2024/05/22 00:45

题目

  http://www.lydsy.com/JudgeOnline/problem.php?id=1007

题解

  调了一上午最后竟然是我的模板打错了555

  半平面交裸题,把所有线段进行半平面交(开口向上),然后看哪些直线在半平面上出现了

  听说正解是用单调栈,就是把所有直线按照斜率排序,然后计算几何各种乱搞。。具体百度吧

代码

#include <cstdio>#include <algorithm>#include <cmath>#define maxn 60000#define finf 1e60using namespace std;int N, seen[maxn], cnt;struct point{double x,y;};struct vec{point a, b;double th;int id;void calc(){th=atan2(b.y-a.y,b.x-a.x);}}q[maxn], seg[maxn];double operator*(vec v1, vec v2){return (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y)-(v2.b.x-v2.a.x)*(v1.b.y-v1.a.y);}bool in(point p, vec v){return (vec){v.a,p}*v<0;}bool operator<(vec v1, vec v2){return v1.th==v2.th?in(v1.a,v2):v1.th<v2.th;}point cross(vec v1, vec v2){double k1, k2, b1, b2, x, y;k1=(v1.a.y-v1.b.y)/(v1.a.x-v1.b.x);k2=(v2.a.y-v2.b.y)/(v2.a.x-v2.b.x);b1=-k1*v1.a.x+v1.a.y;b2=-k2*v2.a.x+v2.a.y;if(v1.a.x==v1.b.x)x=v1.a.x,y=x*k2+b2;else if(v2.a.x==v2.b.x)x=v2.a.x,y=x*k1+b1;else x=(b2-b1)/(k1-k2),y=k1*x+v1.a.y;return (point){x,y};}void input(){int i;double k, b;point p1, p2, p3, p4;scanf("%d",&N);for(i=1;i<=N;i++){scanf("%lf%lf",&k,&b);seg[i]=(vec){(point){0,b},(point){1,k+b}};seg[i].id=i;}p1=(point){finf,finf};p2=(point){-finf,finf};p3=(point){-finf,-finf};p4=(point){finf,-finf};seg[N+1]=(vec){p1,p2};seg[N+2]=(vec){p2,p3};seg[N+3]=(vec){p3,p4};seg[N+4]=(vec){p4,p1};cnt=N+4;}void hpi(){int i, x, l ,r;for(i=1;i<=cnt;i++)seg[i].calc();sort(seg+1,seg+cnt+1);for(i=2,x=1;i<=cnt;i++)if(seg[i].th!=seg[i-1].th)seg[++x]=seg[i];cnt=x;q[l=r=1]=seg[1];for(i=2;i<=cnt;i++){while(l<r and !in(cross(q[r],q[r-1]),seg[i]))r--;while(l<r and !in(cross(q[l],q[l+1]),seg[i]))l++;q[++r]=seg[i];}while(l<r and !in(cross(q[r],q[r-1]),q[l]))r--;while(l<r and !in(cross(q[l],q[l+1]),q[r]))l++;for(i=l;i<=r;i++)seen[q[i].id]=1;}int main(){input();hpi();for(int i=1;i<=N;i++)if(seen[i])printf("%d ",i);return 0;}


0 0