bzoj 1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 5308  Solved: 1990
[Submit][Status][Discuss]

Description

 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.
    例如,对于直线:
    L1:y=x; L2:y=-x; L3:y=0
    则L1和L2是可见的,L3是被覆盖的.
    给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

Input

第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

Output

从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

Sample Input

3
-1 0
1 0
0 0

Sample Output

1 2
题解:

  先按斜率排序,再将最小的一条线入栈,然后依次处理2~N条线,如果第i条直线与stack[top]直线的交点在stack[top]和stack[top-1]直线度左边,则top--,具体可以画几条线模拟一下。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<vector>
 9 using namespace std;
10 const double eps=1e-6;
11 const int maxn=50010;
12 struct bian{
13     double k,b;
14     int id;
15 }str[maxn];
16 int cmp(const bian &x1,const bian &x2){
17     return x1.k<x2.k||(fabs(x1.k-x2.k)<eps&&x1.b<x2.b);
18 }
19 inline double crossx(int x1,int x2){
20     return (str[x2].b-str[x1].b)/(str[x1].k-str[x2].k);
21 }
22 int stack[maxn],top;
23 int N,ans[maxn];
24 int main(){
25     scanf("%d",&N);
26     for(int i=1;i<=N;i++){
27         scanf("%lf%lf",&str[i].k,&str[i].b);
28         str[i].id=i;
29     }
30     sort(str+1,str+N+1,cmp);
31     
32     stack[++top]=1;
33     for(int i=2;i<=N;i++){
34         while(top!=0){
35             if(fabs(str[i].k-str[stack[top]].k)<eps) top--;
36             if((crossx(stack[top-1],i)<=crossx(stack[top-1],stack[top]))&&top>=2)
37                 top--;
38             else break;
39         }
40         stack[++top]=i;
41     }
42     for(int i=1;i<=top;i++) ans[str[stack[i]].id]=1;
43     for(int i=1;i<=N;i++){
44         if(ans[i]==1) printf("%d ",i);
45     }
46     return 0;
47 }

 

原文地址:https://www.cnblogs.com/CXCXCXC/p/5243151.html