BZOJ 1007 HNOI2008 水平可见的直线

本来以为这是一道计算几何的题

可看完题解发现。。。。。。

单调栈即可

按照a为第一关键字b为第二关键字从小到大排序

再将最小的两条线入栈,然后依次处理每条线,如果其与栈顶元素的交点在上一个点的左边,则将栈顶元素出栈 

为什么是对的呢,让我们来看这个图

 

当我们不断往栈里加直线的时候,如果加入的直线与top-1的交点在top和top-1的交点左边,这样的话top的存在是没有任何意义的

因为斜率是单调递增的,所以我们可以用单调栈来维护

#include <bits/stdc++.h>
#define eps 1e-8
using namespace std; 
const int MAXN=1e6+10;
struct node{
    double a,b;
    int id;
}e[MAXN],stark[MAXN];
int n,top=0,vis[MAXN]={};
inline bool mycmp(node n,node m){
    if(abs(n.a-m.a)<=eps) return n.b<m.b;
    else return n.a<m.a;
}
inline double cross(node xx,node yy){
    return (xx.b-yy.b)/(yy.a-xx.a);
}
inline void insert(node xx){
    while(top){
        if(abs(stark[top].a-xx.a)<=eps) top--;
        else if(top>1&&cross(xx,stark[top-1])<=cross(stark[top-1],stark[top])) top--;
        else break;
    }
    stark[++top]=xx;
}
void init(){
    cin>>n;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&e[i].a,&e[i].b);
        e[i].id=i;
    }
    sort(e+1,e+n+1,mycmp);
}
void solve(){
    for(int i=1;i<=n;i++) insert(e[i]);
    for(int i=1;i<=top;i++){
        vis[stark[i].id]=1;
    }
    for(int i=1;i<=n;i++){
        if(vis[i]) printf("%d ",i);
    }
}
int main(){
    //freopen("All.in","r",stdin);
    //freopen("a.out","w",stdout);
    init();
    solve();
    return 0;
}

注意控制精度的问题

 

 

转载于:https://www.cnblogs.com/something-for-nothing/p/7853734.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值