您的位置:首页 > 其它

BZOJ 1007: [HNOI2008]水平可见直线 题解

2017-07-13 19:14 363 查看
(传送门)

其实这道题的求法和凸包类似,首先如果有三条直线i,j,t;并存在


那么如果出现i与j的交点在i与t的交点的左边,那么说明j已经被i和t所覆盖了,用单调栈,把j弹出栈,周而复始。然后……好像也没什么可说的。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct data{
double k,b;
int id;
bool operator < (const data t)const{
return k<t.k||(k==t.k&&b>t.b);
}
double getx(data y){
return (double)(y.b-b)/(k-y.k);
}
}a[50005],stk[50005];
int n,m,top,ans[50005];
int dcmp(double x){
if (fabs(x)<=1e-5) return 0;
return x>0?1:-1;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%lf%lf",&a[i].k,&a[i].b);
a[i].id=i;
}
sort(a+1,a+n+1); m=1; top=0;
for (int i=2;i<=n;i++) if (a[i-1].k<a[i].k) a[++m]=a[i];
for (int i=1;i<=m;i++)
{
while (top>1&&dcmp(stk[top-1].getx(stk[top])-stk[top-1].getx(a[i]))>=0) top--;
stk[++top]=a[i];
}
for (int i=1;i<=top;i++) ans[i]=stk[i].id;
sort(ans+1,ans+top+1);
for (int i=1;i<=top;i++) printf("%d ",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: