B1007 [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),接下来的N行输入Ai,Bi Output 从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格 Sample Input 3 -1 0 1 0 0 0 Sample Output 1 2
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const db eps = 1e-8; struct node { db a,b; int n; }l[50005]; int n,top; bool ans[50005]; node st[50005]; bool cmp(node a,node b) { if(fabs(a.a - b.a) < eps) return a.b < b.b; else return a.a < b.a; } db crossx(node x1,node x2) { return (x2.b - x1.b) / (x1.a - x2.a); } void insert(node a) { while(top) { if(fabs(st[top].a - a.a) < eps) top--; else if(top > 1 && crossx(a,st[top - 1]) <= crossx(st[top],st[top - 1])) top--; else break; } st[++top] = a; } void work() { duke(i,1,n) insert(l[i]); duke(i,1,top) { ans[st[i].n] = 1; } duke(i,1,n) if(ans[i] == 1) printf("%d ",i); } int main() { read(n); duke(i,1,n) { scanf("%lf%lf",&l[i].a,&l[i].b); l[i].n = i; } sort(l + 1,l + n + 1,cmp); work(); return 0; }
只想找一个不会伤害我的人