bzoj1007 [HNOI2008]水平可见直线

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4365  Solved: 1599

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

 

题意:题目就很简明

分析:

先按斜率从小到大排列,如果排序后第1,3的直线遮住了第2的直线,那么2,3的交点必定在1,2的交点的左侧,

证明显然,

综上所述,本题得解

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <deque>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 typedef double DB;
16 #define For(i, s, t) for(int i = (s); i <= (t); i++)
17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
18 #define MIT (2147483647)
19 #define INF (1000000001)
20 #define MLL (1000000000000000001LL)
21 #define sz(x) ((bnt) (x).size())
22 #define clr(x, y) memset(x, y, sizeof(x))
23 #define puf push_front
24 #define pub push_back
25 #define pof pop_front
26 #define pob pop_back
27 #define ft first
28 #define sd second
29 #define mk make_pair
30 inline void SetIO(string Name) {
31     string Input = Name+".in",
32     Output = Name+".out";
33     freopen(Input.c_str(), "r", stdin),
34     freopen(Output.c_str(), "w", stdout);
35 }
36 
37 const int N = 50010;
38 const DB Eps = 1e-5;
39 typedef pair<DB, DB> DD;
40 typedef pair<int, int> II;
41 map<II, int> MAP;
42 II L[N];
43 int n;
44 int Stack[N], Len;
45 
46 inline void Input() {
47     scanf("%d", &n);
48     For(i, 1, n) scanf("%d%d", &L[i].ft, &L[i].sd);
49 }
50 
51 inline DD Work(II L1, II L2) {
52     DB A1 = 1.0*L1.ft, B1 = 1.0*L1.sd, 
53     A2 = 1.0*L2.ft, B2 = 1.0*L2.sd;
54     DD Ret;
55     Ret.ft = (B2-B1)/(A1-A2);
56     Ret.sd = A1*Ret.ft+B1;
57     return Ret;
58 }
59 
60 inline void Solve() {
61     For(i, 1, n) MAP[L[i]] = i;
62     sort(L+1, L+1+n);
63     int _n = n;
64     n = 1;
65     For(i, 2, _n)
66         if(L[i].ft == L[n].ft) L[n] = L[i];
67         else L[++n] = L[i];
68     
69     Stack[1] = 1, Len = 1;
70     For(i, 2, n) {
71         if(Len <= 1) Stack[++Len] = i;
72         else {
73             while(Len >= 2) {
74                 int x = Stack[Len], y = Stack[Len-1];
75                 DD P1 = Work(L[x], L[i]),
76                 P2 = Work(L[y], L[x]);
77                 if(P1.ft <= P2.ft+Eps) Len--;
78                 else break;
79             }
80             Stack[++Len] = i;
81         }
82     }
83     
84     For(i, 1, Len) {
85         int x = Stack[i];
86         x = MAP[L[x]];
87         Stack[i] = x;
88     }
89     sort(Stack+1, Stack+1+Len);
90     For(i, 1, Len) cout<<Stack[i]<<' ';
91 }
92 
93 int main() {
94     SetIO("1007");
95     Input();
96     Solve();
97     return 0;
98 }
View Code

 

思考:原本我是想判断1,3的交点是否在1,2的左侧,如果是则2被覆盖(因为已经按斜率排序了),

我感觉这个做法没问题,可是提交后WA了,请神牛告诉我为什么不对

posted @ 2015-06-19 16:24  yanzx6  阅读(149)  评论(0编辑  收藏  举报