zoukankan      html  css  js  c++  java
  • [HNOI2008] [BZOJ1007] 水平可见直线|乱搞

    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
     
    //省选Round1之前写了俩晚上一直过不了。在Round1之前的那晚突然明白了错在哪了,暴力递归+贪心果然有bug。所以今天直接重新用栈写的。成功AC。
     
    分析:
    经过分析,我们可以先双关键字将所有直线进行排序。维护一个栈,每次向栈里从小到大加直线,判断栈顶的三条直线,设为l1,l2,l3吧。若l1 l2的交点在l2,l3交点的右边,那么l2就会被彻底覆盖,visit数组赋成false。继续递归。若不会被覆盖,则加进栈中此条边,继续处理下一条边。
    对于斜率相同截距不同的直线直接特殊处理就好。
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<vector>
    #include<cmath>
    using namespace std;
    struct node
    {
        double k,b;
        int num;
    };
    node q[55555],a[55555];
    int n,top;
    double x1,x2;
    bool visit[55555];
    bool cmp(node x,node y)
    {
         return x.k<y.k||x.k==y.k&&x.b>y.b;
    }
    double calc(node x,node y)
    {
        return (x.b-y.b)/(y.k-x.k);
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) 
        {
            scanf("%lf%lf",&a[i].k,&a[i].b);
            a[i].num=i;
        }
        sort(a+1,a+n+1,cmp);
        memset(visit,1,sizeof(visit));
        top=0;
        for (int i=1;i<=n;i++)
        {
            if (top==0)
            {
                q[++top]=a[i];
                continue;
            }
            if (q[top].k==a[i].k) 
            {
                visit[a[i].num]=false;
                continue;
            }
            if (top==1)
            {
                q[++top]=a[i];
                continue;
            }
            while (1)
            {
                if (top==1) 
                {
                    q[++top]=a[i];
                    break;
                }
                x1=calc(q[top],a[i]);
                x2=calc(q[top-1],q[top]);
                if (x1<=x2)
                {
                    visit[q[top].num]=false;
                    top--;
                }
                else 
                {
                     q[++top]=a[i];
                     break;
                }
            }
        }
        for (int i=1;i<=n;i++) if (visit[i]) printf("%d ",i);
        return 0;
    }
  • 相关阅读:
    前端 http协议 四大特性 web本质 -响应状态码 列表标签 表单操作 form表单 # 44 HTML
    断点传续 # 补充 mysql
    优酷系统 # 41-43
    css控制 只显示一行 强制不换行 超出用...表示
    点击返回上一页面
    jquery实现点击按钮变换背景颜色
    js,同意后,才可已点击注册按钮
    用div+css生存太极图案
    使用tp5,显示页面错误信息
    vue项目搭建步骤
  • 原文地址:https://www.cnblogs.com/ws-fqk/p/4455931.html
Copyright © 2011-2022 走看看