bzoj1007:[HNOI2008]水平可见直线

思路:首先按斜率排序,如果斜率相同就取截距最大的,显然截距小的会被覆盖而对答案没有贡献,然后考虑斜率不同的如何统计答案,可以用一个单调栈维护,当前新插入的直线显然斜率是要比当前栈顶斜率要大的,然后如果新插入的直线l[i]与stack[top]的交点在stack[top]与stack[top-1]的交点的右边,那么就不需要退栈直接加进来就好了,否则就要退栈直到条件成立。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 50005
#define eps 1e-7
 
int n,cnt,top,stack[maxn];
 
struct line{
    double k,b;
    int id;
    bool operator <(const line &a)const{return k<a.k ||(fabs(k-a.k)<eps && b<a.b);}
}l[maxn];
 
bool cmp(int a,int b){return l[a].id<l[b].id;}
 
double getpoint_x(line a,line b){
    return (b.b-a.b)/(a.k-b.k);
}
 
bool check(line a,line b,line c){
    return getpoint_x(a,b)>=getpoint_x(b,c);
}
 
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%lf%lf",&l[i].k,&l[i].b),l[i].id=i;
    sort(l+1,l+n+1);
    for (int i=1;i<=n;i++){
        while (fabs(l[i].k-l[i+1].k)<eps) i++;
        while (top>=2 && check(l[stack[top-1]],l[stack[top]],l[i])) top--;
        stack[++top]=i;
    }
    sort(stack+1,stack+top+1,cmp);
    for (int i=1;i<=top;i++) printf("%d ",l[stack[i]].id);
    return 0;
}

 

posted @ 2016-10-28 11:04  DUXT  阅读(163)  评论(0编辑  收藏  举报