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-8

struct 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;
}
原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6790277.html