【BZOJ】【1007】【HNOI2008】水平可见直线
计算几何初步
其实是维护一个类似下凸壳的东西?画图后发现其实斜率是单调递增的,交点的横坐标也是单调递增的,所以排序一下搞个单调栈来做就可以了……
看了hzwer的做法……
1 /************************************************************** 2 Problem: 1007 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:252 ms 7 Memory:2812 kb 8 ****************************************************************/ 9 10 //BZOJ 1007 11 #include<cstdio> 12 #include<cmath> 13 #include<cstdlib> 14 #include<algorithm> 15 #define F(i,j,n) for(int i=j;i<=n;++i) 16 using namespace std; 17 const double eps=1e-8; 18 const int N=50001; 19 struct data{double a,b;int n;}l[N],st[N]; 20 bool ans[N]; 21 int top,n; 22 inline bool cmp(data a,data b){ 23 if (fabs(a.a-b.a)<eps) return a.b<b.b; 24 return a.a<b.a; 25 } 26 double crossx(data x1,data x2){ 27 return (x2.b-x1.b)/(x1.a-x2.a); 28 } 29 void insert(data a){ 30 while(top){ 31 if (fabs(st[top].a-a.a)<eps) top--; 32 else if(top>1 && crossx(a,st[top-1])<=crossx(st[top],st[top-1])) 33 top--; 34 else break; 35 } 36 st[++top]=a; 37 } 38 void work(){ 39 F(i,1,n) insert(l[i]); 40 F(i,1,top) ans[st[i].n]=1; 41 F(i,1,n) if (ans[i]) printf("%d ",i); 42 } 43 int main(){ 44 scanf("%d",&n); 45 F(i,1,n){ 46 scanf("%lf%lf",&l[i].a,&l[i].b); 47 l[i].n=i; 48 } 49 sort(l+1,l+n+1,cmp); 50 work(); 51 return 0; 52 } 53
1007: [HNOI2008]水平可见直线
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4154 Solved: 1520
[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