[BZOJ1007](HNOI2008)水平可见直线(半平面交习题)
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
-1 0
1 0
0 0
Sample Output
1 2
分析
半平面交的模板题。维护一个栈,把所有边按极角排序后依次插入,每次弹出所有可以被覆盖的直线。
1 /**************************************************************
2 Problem: 1007
3 User: AsmDef
4 Language: C++
5 Result: Accepted
6 Time:124 ms
7 Memory:2496 kb
8 ****************************************************************/
9
10 //Asm.Def
11 #include <cctype>
12 #include <cstdio>
13 #include <iostream>
14 #include <cmath>
15 #include <cstdlib>
16 #include <algorithm>
17 #include <assert.h>
18 using namespace std;
19 inline void getd(int &x){
20 char c = getchar(); bool minus = 0;
21 while(!isdigit(c) && c != '-')c = getchar();
22 if(c == '-')minus = 1, c = getchar();
23 x = c - '0';
24 while(isdigit(c = getchar()))x = x * 10 + c - '0';
25 if(minus)x = -x;
26 }
27 /*========================================================*/
28 const int maxn = 50003;
29 typedef long long LL;
30 int N;
31 struct Line{
32 int id;
33 int A, B;
34 }line[maxn], St[maxn];
35 bool operator < (const Line &a, const Line &b){return b.A > a.A;}
36 inline void init(){
37 getd(N);int i;
38 for(i = 1;i <= N;++i)
39 getd(line[i].A), getd(line[i].B), line[i].id = i;
40 sort(line + 1, line + N + 1);
41 }
42 int it = 0;
43 bool inS[maxn];
44 inline void work(){
45 int i;
46 St[it++] = line[1];
47 for(i = 2;i <= N;++i){
48 if(line[i].A == St[it-1].A){
49 if(line[i].B > St[it-1].B)
50 St[it-1] = line[i];
51 else continue;
52 }
53 while(it > 1){
54 LL a = (LL)(St[it-2].B - St[it-1].B) * (line[i].A - St[it-1].A);
55 LL b = (LL)(St[it-1].B - line[i].B) * (St[it-1].A - St[it-2].A);
56 if(a >= b)--it;
57 else break;
58 }
59 St[it++] = line[i];
60 }
61 while(it)inS[St[--it].id] = 1;
62 for(i = 1;i <= N;++i)
63 if(inS[i]) printf("%d ", i);
64 }
65 int main(){
66 #if defined DEBUG
67 freopen("test", "r", stdin);
68 #endif
69 init();
70 work();
71
72 return 0;
73 }
2 Problem: 1007
3 User: AsmDef
4 Language: C++
5 Result: Accepted
6 Time:124 ms
7 Memory:2496 kb
8 ****************************************************************/
9
10 //Asm.Def
11 #include <cctype>
12 #include <cstdio>
13 #include <iostream>
14 #include <cmath>
15 #include <cstdlib>
16 #include <algorithm>
17 #include <assert.h>
18 using namespace std;
19 inline void getd(int &x){
20 char c = getchar(); bool minus = 0;
21 while(!isdigit(c) && c != '-')c = getchar();
22 if(c == '-')minus = 1, c = getchar();
23 x = c - '0';
24 while(isdigit(c = getchar()))x = x * 10 + c - '0';
25 if(minus)x = -x;
26 }
27 /*========================================================*/
28 const int maxn = 50003;
29 typedef long long LL;
30 int N;
31 struct Line{
32 int id;
33 int A, B;
34 }line[maxn], St[maxn];
35 bool operator < (const Line &a, const Line &b){return b.A > a.A;}
36 inline void init(){
37 getd(N);int i;
38 for(i = 1;i <= N;++i)
39 getd(line[i].A), getd(line[i].B), line[i].id = i;
40 sort(line + 1, line + N + 1);
41 }
42 int it = 0;
43 bool inS[maxn];
44 inline void work(){
45 int i;
46 St[it++] = line[1];
47 for(i = 2;i <= N;++i){
48 if(line[i].A == St[it-1].A){
49 if(line[i].B > St[it-1].B)
50 St[it-1] = line[i];
51 else continue;
52 }
53 while(it > 1){
54 LL a = (LL)(St[it-2].B - St[it-1].B) * (line[i].A - St[it-1].A);
55 LL b = (LL)(St[it-1].B - line[i].B) * (St[it-1].A - St[it-2].A);
56 if(a >= b)--it;
57 else break;
58 }
59 St[it++] = line[i];
60 }
61 while(it)inS[St[--it].id] = 1;
62 for(i = 1;i <= N;++i)
63 if(inS[i]) printf("%d ", i);
64 }
65 int main(){
66 #if defined DEBUG
67 freopen("test", "r", stdin);
68 #endif
69 init();
70 work();
71
72 return 0;
73 }