[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

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 }
半平面交

 

posted @ 2015-03-26 11:08  Asm.Definer  阅读(214)  评论(0编辑  收藏  举报