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 }