bzoj 1007[HNOI2008]水平可见直线 - 半平面交

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB

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

 

 

可以想象最终在上面的图形是一个半凸包
所以只需要按照斜率排序
将前面的直线都推到一个栈里
如果新加入的直线和栈顶直线交点在之前交点的左面
那么凸包栈顶的直线就被覆盖了,弹出就可以了

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define LL long long
 6 
 7 using namespace std;
 8 
 9 const int MAXN = 5e4 + 10;
10 
11 int N;
12 int top = 0;
13 int ans[MAXN];
14 int sta[MAXN];
15 double x[MAXN];
16 
17 struct line {
18     double k;
19     double b;
20     int id;
21 } l[MAXN];
22 
23 bool cmp(line a, line b)
24 {
25     if(a.k == b.k) {
26         return a.b > b.b;
27     }
28     return a.k < b.k;
29 }
30 
31 inline LL read()
32 {
33     LL x = 0, w = 1; char ch = 0;
34     while(ch < '0' || ch > '9') {
35         if(ch == '-') {
36             w = -1;
37         }
38         ch = getchar();
39     }
40     while(ch >= '0' && ch <= '9') {
41         x = x * 10 + ch - '0';
42         ch = getchar();
43     }
44     return x * w;
45 }
46 
47 double intersaction(int a, int b)
48 {
49     return (l[b].b - l[a].b) / (l[a].k - l[b].k);
50 }
51 int main()
52 {
53     N = read();
54     for(int i = 1; i <= N; i++) {
55         scanf("%lf%lf", &l[i].k, &l[i].b);
56         l[i].id = i;
57     }
58     sort(l + 1, l + N + 1, cmp);
59     sta[0] = 1;
60     top = 1;
61     for(int i = 2; i <= N; i++) {
62         if(l[i].k == l[sta[top - 1]].k) {
63             continue;
64         }
65         while(intersaction(i, sta[top - 1]) <= intersaction(sta[top - 1], sta[top - 2]) && top > 1) {
66             top--;
67         }
68         top++;
69         sta[top - 1] = i;
70     }
71     for(int i = 0; i < top; i++) {
72         ans[l[sta[i]].id] = 1;
73     }
74     for(int i = 1; i <= N; i++) {
75         if(ans[i]) {
76             printf("%d ", i);
77         }
78     }
79     return 0;
80 }
View Code

 

posted @ 2018-01-30 23:16  大财主  阅读(172)  评论(0编辑  收藏  举报