bzoj 1007 水平可见直线

题目大意:

有一些直线若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的

思路:

可以看出来最后图形应该为一个下凸包

对于下凸包上的每个点,斜率都应该递增,而且横坐标递增

因此我们先对每条线的斜率进行排序

然后使用单调栈维护即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<set>
 8 #include<map>
 9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 50100
15 using namespace std;
16 inline ll read()
17 {
18     ll x=0,f=1;
19     char ch;ch=getchar();
20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
22     return x*f;
23 }
24 struct sline
25 {
26     double k,b;
27     int num;
28 }l[MAXN],st[MAXN];
29 const double eps=1e-8;
30 bool cmp1(sline A,sline B) {return A.k<B.k||(fabs(A.k-B.k)<eps&&A.b<B.b);}
31 bool cmp2(sline A,sline B) {return A.num<B.num;}
32 double insct(sline A,sline B)
33 {
34     return (B.b-A.b)/(A.k-B.k);
35 }
36 int n,top;
37 int main()
38 {
39     n=read();
40     for(int i=1;i<=n;i++) {scanf("%lf%lf",&l[i].k,&l[i].b);l[i].num=i;}
41     sort(l+1,l+n+1,cmp1);
42     for(int i=1;i<=n;i++)
43     {
44         while(fabs(st[top].k-l[i].k)<eps&&top) top--;
45         while(insct(st[top],st[top-1])>=insct(l[i],st[top-1])&&top>1) top--;
46         st[++top]=l[i];
47     }
48     sort(st+1,st+top+1,cmp2);
49     for(int i=1;i<=top;i++) printf("%d ",st[i].num);
50 }
View Code
posted @ 2017-10-23 18:56  jack_yyc  阅读(135)  评论(0编辑  收藏  举报