zoukankan      html  css  js  c++  java
  • BZOJ 1007 [HNOI2008]水平可见直线

    1007: [HNOI2008]水平可见直线

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 4453  Solved: 1636
    [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

    HINT

     

    Source

     题解:做的第一道计算几何。。。

    要维护的是一个下凸线一样的东西。即从左到右的交点(左)右边的直线是斜率越来越大的。

    所以我们可以按斜率从小到大排序后。用一个栈来这样维护。

    每次新加一条直线k,设当前栈顶直线为stack[top]=j,栈顶前一条直线为stack[top-1]=i,则若(k,j)的交点在(i,j)交点的左边或重合,则j必是被k与i及之前的直线所完全覆盖的,所以把j pop 出。直到不能再pop为止,再把k加入栈中。

    上来忘了unique了,我是个脑残。。。被题目中的任一两线不重合骗了QAQ。。。

    还有!!!这种stack一定要写数!组!版!的!

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<stack>
     7 #include<cstring>
     8 #define PAU putchar(' ')
     9 #define ENT putchar('
    ')
    10 using namespace std;
    11 const int maxn=50000+10;const double esp=1e-9;
    12 struct line{int id,k,b;line(int _id=1,int _k=0.0,int _b=0.0){id=_id;k=_k;b=_b;}}L[maxn],S[maxn];
    13 bool operator<(const line&a,const line&b){return (a.k<b.k)||(a.k==b.k&&a.b>b.b);}
    14 bool operator==(const line&a,const line&b){return a.k==b.k;}
    15 double getx(line&a,line&b){
    16     return (double)(b.b-a.b)/(double)(a.k-b.k);
    17 }
    18 int n,ans[maxn],top=1;
    19 inline int read(){
    20     int x=0,sig=1;char ch=getchar();
    21     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
    22     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
    23     return x*=sig;
    24 }
    25 inline void write(int x){
    26     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
    27     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
    28     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
    29 }
    30 void init(){
    31     n=read();int x,y;
    32     for(int i=1;i<=n;i++){x=read();y=read();L[i]=line(i,x,y);}
    33     return;
    34 }
    35 void work(){
    36     sort(L+1,L+n+1);n=unique(L+1,L+n+1)-L-1;
    37     for(int i=1;i<=n;i++){
    38         while(top>2&&getx(S[top-1],S[top-2])>getx(S[top-1],L[i])-esp)top--;
    39         S[top++]=L[i];
    40     }
    41     for(int i=1;i<top;i++)ans[i]=S[i].id;
    42     sort(ans+1,ans+top);
    43     return;
    44 }
    45 void print(){
    46     for(int i=1;i<top;i++)write(ans[i]),PAU;
    47     return;
    48 }
    49 int main(){
    50     init();work();print();return 0;
    51 }
  • 相关阅读:
    sql行列互转
    用户角色权限设计思路
    树节点类型数据的Datatable转Json
    [C#]最简单的Base64加密解密
    WEB打印控件Lodop(V6.x)使用说明及样例
    js代码 设为首页 加入收藏
    Json字符转化成对象
    C++函数返回值为const
    7.双指针(two pointer)
    线程同步与锁
  • 原文地址:https://www.cnblogs.com/chxer/p/4640803.html
Copyright © 2011-2022 走看看