【BZOJ】【1007】【HNOI2008】水平可见直线

计算几何初步


  其实是维护一个类似下凸壳的东西?画图后发现其实斜率是单调递增的,交点的横坐标也是单调递增的,所以排序一下搞个单调栈来做就可以了……

  看了hzwer的做法……

 1 /**************************************************************
 2     Problem: 1007
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:252 ms
 7     Memory:2812 kb
 8 ****************************************************************/
 9  
10 //BZOJ 1007
11 #include<cstdio>
12 #include<cmath>
13 #include<cstdlib>
14 #include<algorithm>
15 #define F(i,j,n) for(int i=j;i<=n;++i)
16 using namespace std;
17 const double eps=1e-8;
18 const int N=50001;
19 struct data{double a,b;int n;}l[N],st[N];
20 bool ans[N];
21 int top,n;
22 inline bool cmp(data a,data b){
23     if (fabs(a.a-b.a)<eps) return a.b<b.b;
24     return a.a<b.a;
25 }
26 double crossx(data x1,data x2){
27     return (x2.b-x1.b)/(x1.a-x2.a);
28 }
29 void insert(data a){
30     while(top){
31         if (fabs(st[top].a-a.a)<eps) top--;
32         else if(top>1 && crossx(a,st[top-1])<=crossx(st[top],st[top-1]))
33             top--;
34         else break;
35     }
36     st[++top]=a;
37 }
38 void work(){
39     F(i,1,n) insert(l[i]);
40     F(i,1,top) ans[st[i].n]=1;
41     F(i,1,n) if (ans[i]) printf("%d ",i);
42 }
43 int main(){
44     scanf("%d",&n);
45     F(i,1,n){
46         scanf("%lf%lf",&l[i].a,&l[i].b);
47         l[i].n=i;
48     }
49     sort(l+1,l+n+1,cmp);
50     work();
51     return 0;
52 }
53 
View Code

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4154  Solved: 1520
[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

HINT

Source

[Submit][Status][Discuss]
posted @ 2015-04-13 18:16  Tunix  阅读(251)  评论(0编辑  收藏  举报