BZOJ 1007-水平可见直线

来源:互联网 发布:财达大智慧软件下载 编辑:程序博客网 时间:2024/06/14 05:19

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 7439  Solved: 2849
[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

Sample Output

1 2

本来是没有思路的,但是在纸上画画,很容易看出来

一条直线被遮盖当且仅当该直线与比他斜率大的直线的交点在该直线与比他小的直线的交点左侧
因此只需对斜率从小到大排个序,然后栈模拟一下就好啦(注意:斜率相同的时候保留截距大的直线即可)

#include<map>#include<stack>#include<queue>#include<vector>#include<math.h>#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>using namespace std;typedef long long  ll;#define  maxn 51005int s[maxn],b[maxn],top;struct node{int k,b,id;}a[maxn];bool comp(node a,node b){if(a.k==b.k)return a.b>b.b;return a.k<b.k;}double Slope(node a,node b){return (double)(b.b-a.b)/(double)(a.k-b.k);}void push(int x){while(top>1 && Slope(a[s[top]],a[x])<=Slope(a[s[top]],a[s[top-1]]))top--;s[++top]=x;}int main(void){int n,i,j;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d%d",&a[i].k,&a[i].b);a[i].id=i;}sort(a+1,a+n+1,comp);push(1);for(i=2;i<=n;i++)if(a[i].k>a[i-1].k)push(i);for(i=1;i<=top;i++)b[a[s[i]].id]=1;for(i=1;i<=n;i++)if(b[i])printf("%d ",i);printf("\n");return 0;}


原创粉丝点击