bzoj 1007 [HNOI2008]水平可见直线(单调栈)
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5120 Solved: 1899
[Submit][Status][Discuss]
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 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 6 using namespace std; 7 8 const int N = 50000+10; 9 const double eps = 1e-8; 10 11 struct Line { 12 double a,b; int r; 13 bool operator < (const Line& rhs) const { 14 if(fabs(a-rhs.a)<eps) return b<rhs.b; 15 else return a<rhs.a; 16 } 17 }L[N],S[N]; 18 19 double cross(Line x1,Line x2) { 20 return (x2.b-x1.b)/(x1.a-x2.a); 21 } 22 23 int n,flag[N],top; 24 25 int main() { 26 scanf("%d",&n); 27 FOR(i,1,n) { 28 scanf("%lf%lf",&L[i].a,&L[i].b); 29 L[i].r=i; 30 } 31 sort(L+1,L+n+1); 32 FOR(i,1,n) { 33 while(top) { 34 if(fabs(S[top].a-L[i].a)<eps) top--; 35 else if(top>1 && cross(L[i],S[top-1])<=cross(S[top],S[top-1])) top--; 36 else break; 37 } 38 S[++top]=L[i]; 39 } 40 FOR(i,1,top) flag[S[i].r]=1; 41 FOR(i,1,n) if(flag[i]) 42 printf("%d ",i); 43 return 0; 44 }
posted on 2016-02-02 09:10 hahalidaxin 阅读(291) 评论(0) 编辑 收藏 举报