• [HNOI2008]水平可见直线


    1007: [HNOI2008]水平可见直线

    Time Limit: 1 Sec  Memory Limit: 162 MB
    [Submit][Status][Discuss]

    Description

      在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
    可见的,否则Li为被覆盖的.
    例如,对于直线:
    L1:y=x; L2:y=-x; L3:y=0
    则L1和L2是可见的,L3是被覆盖的.
    给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

    Input

      第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

    Output

      从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

    Sample Input

    3
    -1 0
    1 0
    0 0

    Sample Output

    1 2
     
    将所有线段按斜率从大到小排序
    斜率相等的直线只保留截距最大的
    枚举直线
    当前枚举的直线是已枚举的直线中斜率最小的
    所以交点左侧全部被当前直线遮挡
    所以之前枚举的直线是否被遮挡取决于交点右侧
    设l为当前直线,l1为斜率次小直线,l2为斜率次次小直线
    x1为l与l1的交点,x2为l与l2的交点,
    l1要想不被遮挡,必须满足x1<x2
    用单调栈维护这一过程
    每次取出栈顶和栈顶的下一个,判断栈顶是否出栈
     
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #define N 50001
    using namespace std;
    const double eps=1e-6;
    struct node
    {
        double A,B;
        int id;
    }e[N];
    int st[N],top;
    int ans[N];
    bool cmp(node p,node q)
    {
        if(abs(p.A-q.A)>eps) return p.A>q.A;
        return p.B>q.B;
    }
    int main()
    {
        int n,tot=0,last=1e9,a,b;
        scanf("%d",&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,cmp);
        for(int i=1;i<=n;i++)
            if(e[i].A!=e[i-1].A) e[++tot]=e[i];
        if(tot<=2) 
        {
            for(int i=1;i<=tot;i++) ans[i]=e[i].id;
            sort(ans+1,ans+tot+1);
            for(int i=1;i<=tot;i++) printf("%d ",ans[i]);
            return 0;
        }
        st[++top]=1;
        st[++top]=2;
        double x1,x2;
        for(int i=3;i<=tot;i++)
        {
            while(top>1)
            {
                x1=(e[st[top]].B-e[i].B)/(e[i].A-e[st[top]].A);
                x2=(e[st[top-1]].B-e[i].B)/(e[i].A-e[st[top-1]].A);
                if(x1<x2) break;
                else top--;
            }
            st[++top]=i;
        }
        for(int i=1;i<=top;i++) ans[i]=e[st[i]].id;
        sort(ans+1,ans+top+1);
        for(int i=1;i<=top;i++) printf("%d ",ans[i]);
    }
  • 相关阅读:
    DJANGO
    前端--BootStrap
    前端--JQuery
    前端--JavaScript
    前端--CSS
    前端--HTML
    python中面试题积累
    python中一些小的知识点
    python中字典的增删改查及相关知识点
    python中列表的增删改查以及其它相关方法
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7466010.html
Copyright © 2020-2023  润新知