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

解析:模拟水题,但我一开始没过是因为类型不对……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

struct node{
    double a,b;
    int num;
}l[50001],s[50001];
int tot=0,top=0;

bool cmp(node a,node b)
{
    if (a.a!=b.a) return a.a<b.a;
    return a.b>b.b;
} 

bool cmp2(node a,node b) { return a.num<b.num;  }

inline void insert(node x)
{
    if (s[top].a==x.a) return;
    if (top<2) { s[++top]=x; return; }
    while (1)
    {
        if (top==1) { s[++top]=x; return; }
        double x1=(s[top].b-x.b)/(x.a-s[top].a);
        double x2=(s[top].b-s[top-1].b)/(s[top-1].a-s[top].a);
        if (x1<=x2 || (x1-x2)<0.00001) top--;
            else { s[++top]=x; return;    }
    }
    return;
}

int main()
{
    int n;
    scanf("%d",&n);
    if (n==1) cout << 1 << endl;
    for (int i=1; i<=n; i++) { tot++; scanf("%lf%lf",&l[tot].a,&l[tot].b); l[tot].num=i; }
    if (n==2)
        if (l[1].a==l[2].a) { if (l[1].b>l[2].b) cout << 1; else cout << 2;  }
            else cout << 1 << " " << 2;
    sort(l+1,l+n+1,cmp);
    for (int i=1; i<=n; i++) insert(l[i]);
    sort(s+1,s+top+1,cmp2);
    for (int i=1; i<=top; i++) cout << s[i].num << " ";
    return 0;
} 
时间: 2024-10-29 22:14:35

BZOJ1007|水平可见直线|模拟的相关文章

[BZOJ1007]水平可见直线

发现其实是一个下凸壳,所以先按斜率排序,然后判断当前直线与栈顶直线的交点是否更靠右 注意平行的情况 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define maxn 50005 5 #define esp 1e-8 6 struct node{ 7 double a,b; 8 int id; 9 }V[maxn]; 10 double a[maxn],b[maxn]; 11 int sta[maxn],top; 12 bool

[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行输入A

BZOJ1007 水平相交直线

按照斜率排序,我们可以想象如果你能看到大于等于三条直线那么他一定会组成一个下凸包,这样我们只需要判断如果当前这条直线与栈顶第二直线相交点相比于栈顶第二直线与栈顶直线相交点靠左那么他就不满足凸包性质. 画画图想想看. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1000005; 4 double eps=1e-8; 5 bool ans[1000005]; 6 struct node 7 { 8 double k,

【BZOJ1007】[HNOI2008]水平可见直线 半平面交

[BZOJ1007][HNOI2008]水平可见直线 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

bzoj1007: [HNOI2008]水平可见直线(单调栈)

1007: [HNOI2008]水平可见直线 题目:传送门 题解: 蒟蒻在bzoj上做的第一道计算几何 其实这道题并不难...(所以我A了) 仔细想想不难发现,其实我们只需要维护一个下凸的图形... 只有在这个图形上的直线才不会被覆盖,也就是可以被上帝直线看到的孩子 为什么呢...自己画个图模拟吧. 那么具体的做法我们就要采用单调栈啦! 把给出的直线按照斜率从小到大排序(如果斜率相同的话就按照b来排) 然后一个一个放入我们强大的单调栈中,在加入的同时我们当然还要进行维护: 如果栈顶的直线与新加直

【BZOJ1007】水平可见直线(单调栈)

[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 < 50

BZOJ 1007: [HNOI2008]水平可见直线 几何

按斜率排序,斜率线相同的直线取截距最大的 一条直线能够被看到的条件是,与比它斜率小的交点在比它斜率大的交点的左侧 1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 4234  Solved: 1558 [Submit][Status][Discuss] Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则

bzoj 1007 水平可见直线 半平面交稀里糊涂的过了...

题意:按y=Ax+B的形式给出n(<=50000)条直线,求从y值为无穷大的地方向下看能看到的直线编号 一看到题目就想到半平面交,以每条直线的上方为一个半平面,求半平面的交,交集中存在的直线就是能看到的直线 但是写出来之后发现样例都过不了... 对于样例,如果允许半平面在边界处重叠那么答案是1,2,3,如果不允许只有1.. 然后抱着试一试的心理交上去了,结果竟然直接AC了.. 后来看题解只需要考虑交点x坐标.. bzoj 1007 水平可见直线 半平面交稀里糊涂的过了...,布布扣,bubuko

1007: [HNOI2008]水平可见直线[维护下凸壳]

1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 7184  Solved: 2741[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是被覆盖的.给