首页 > 代码库 > AC日记——[HNOI2008]水平可见直线 bzoj 1007

AC日记——[HNOI2008]水平可见直线 bzoj 1007

1007

 

思路:

  维护一个下凸壳;

  用单调栈来维护这玩意儿;

  先将斜率排序;

  然后判断栈顶元素和当前元素的交点x是否小于栈顶元素和栈顶上一个元素的交点x;

  注意:

    人神共愤的精度问题和输出空格问题;

 

来,上代码:

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define maxn 50005#define eps 1e-8struct LineType {    int k,b,id;};struct LineType line[maxn];int n,sta[maxn],top=0,ans[maxn];inline void in(int &now){    int if_z=1;now=0;    char Cget=getchar();    while(Cget>9||Cget<0)    {        if(Cget==-) if_z=-1;        Cget=getchar();    }    while(Cget>=0&&Cget<=9)    {        now=now*10+Cget-0;        Cget=getchar();    }    now*=if_z;}bool cmp(LineType aa,LineType bb){    if(aa.k==bb.k) return aa.b<bb.b;    return aa.k<bb.k;}double xx(int a,int b){    double up=line[b].b-line[a].b;    double down=line[a].k-line[b].k;    return up/down;}int main(){    in(n);    for(int i=1;i<=n;i++) in(line[i].k),in(line[i].b),line[i].id=i;    sort(line+1,line+n+1,cmp);    for(int i=1;i<=n;i++)    {        if(!top||top==1)        {            if(top==1)            {                if(line[sta[top]].k==line[i].k)                {                    sta[top]=i;                    continue;                }            }            sta[++top]=i;            continue;        }        while(line[sta[top]].k==line[i].k) top--;        while(top>1&&xx(sta[top-1],i)-xx(sta[top],i)>eps) top--;        sta[++top]=i;    }    for(int i=1;i<=top;i++) ans[i]=line[sta[i]].id;    sort(ans+1,ans+top+1);    for(int i=1;i<=top;i++) printf("%d ",ans[i]);    return 0;}

 

AC日记——[HNOI2008]水平可见直线 bzoj 1007