• 1007: [HNOI2008]水平可见直线


    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 8846  Solved: 3418
    [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
     
    手贱少写了个return,70分卡了我半天。。。编译器还不提示T_T
    排序+单调栈
    stack一定要写数组版,别偷懒了!!!
    根据题意,k是一定存在的,不需要考虑k不存在时的情况(数学题做多了)
    显然斜率A相同时,B越大的直线可见,所以要排除掉斜率相同,截距较小的直线
    推算几组数据后可得知,斜率是由小到大递增的,斜率最小和最大的两条直线一定是可见的,并且某条直线可见,则最先与其相交的直线也可见
    如何判断哪条直线先相交呢?则是通过判断交点横坐标的位置来确定的
    交点坐标计算公式证明:
      y=A1x+B1
      y=A2x+B2
    解得:

    [x=frac{B2-B1}{A1-A2}]

    比如说A,B,C 三条直线

    如果A与B交点的横坐标在B与C的左边,则说明三条直线都可见。

    如果A与B交点的横坐标在B与C的右边,则说明B是不可见的,要删掉。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 
     7 const int MAXN=50000+5;
     8 struct Line
     9 {
    10     int a,b,id;
    11 }L[MAXN];
    12 int st[MAXN],ans[MAXN];
    13 int n,top;
    14 
    15 bool cmp(Line A,Line B)
    16 {
    17     if(A.a!=B.a)
    18         return A.a<B.a;
    19     else return A.b>B.b;
    20 }
    21 
    22 double getx(int A,int B)
    23 {
    24     return (double)(L[B].b-L[A].b)/(double)(L[A].a-L[B].a);
    25 }
    26 
    27 int main()
    28 {
    29     scanf("%d",&n);
    30     for(int i=1;i<=n;i++)
    31     {
    32         scanf("%d %d",&L[i].a,&L[i].b);
    33         L[i].id=i;
    34     }
    35     sort(L+1,L+n+1,cmp);
    36     for(int i=1;i<=n;i++)
    37     {
    38         if(i!=1&&L[i-1].a==L[i].a) continue;
    39         while(top>1&&getx(st[top],i)<=getx(st[top-1],st[top])) top--;
    40         st[++top]=i;
    41         ans[top]=L[i].id;
    42     }
    43     sort(ans+1,ans+top+1);
    44     for(int i=1;i<=top;i++) printf("%d ",ans[i]);
    45     return 0;
    46 }
  • 相关阅读:
    小透明学弟的华为上岸之路
    手把手体验远程开发,确实爽
    老弟做了个网盘,炸了!
    聊聊我在腾讯和字节工作感受
    2021,编程语言如何选择?
    优化了破网站的搜索功能
    15 道超经典大厂 Java 面试题!重中之重
    我两年的坚持,值了!
    聊聊百度搜索背后的故事
    struts2的配置步骤
  • 原文地址:https://www.cnblogs.com/InWILL/p/9275789.html
Copyright © 2020-2023  润新知