bzoj1007 [HNOI2008]水平可见直线
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 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
-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 }
思考:原本我是想判断1,3的交点是否在1,2的左侧,如果是则2被覆盖(因为已经按斜率排序了),
我感觉这个做法没问题,可是提交后WA了,请神牛告诉我为什么不对