Submit: 8638 Solved: 3327
[Submit][Status][Discuss]
Description
There are n straight lines L1, L2,...Ln on the xoy rectangular coordinate plane. If you look down at the y value of positive infinity, if you can see a certain sub-line segment of Li, then Li is called
visible, otherwise Li is Covered.
For example, for a line:
L1:y=x; L2:y=-x; L3:y=0
then L1 and L2 are visible and L3 is covered.
Given n lines, denoted as y =Ax+B (|A|, |B|<=500000), and the n lines do not overlap each other. Find all visible lines.
Input
The first line is N (0 < N < 50000), and the next N lines enter Ai, Bi
Output
The number of visible lines is output from small to large, separated by spaces, and there must be a space after the last number
Sample Input
-1 0
1 0
0 0
Sample Output
HINT
Source
My train of thought:
For a straight line, if it is invisible, there are only two cases
One: blocked by a straight line with the same slope, but $b$ is larger than it
Two: blocked by two intersecting straight lines, which is the following situation
For the first case, a direct judgment can be
For the second case, there are some troubles to deal with directly, so we consider first sorting by slope from small to large
Maintain a stack at the same time
If the intersection of the current line and the previous element of the top element is to the left of the abscissa of the intersection of the top element and the previous element of the stack, then the previous element at the top of the stack is useless
Finally, you can count which elements are in the stack
Similar to a monotonic stack
Time complexity: $O(n)$
#include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int MAXN = 200001; const double eps = 1e-7; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} return x *f; } int N; struct Seg { int ID; double k, b; bool operator < (const Seg &rhs) const { return fabs(k - rhs.k) <= eps ? b < rhs.b : k < rhs.k; } }a[MAXN], S[MAXN]; int top = 0; int Ans[MAXN]; double X(Seg x, Seg y) { return (y.b - x.b) / (x.k - y.k); } void Solve() { fill(Years + 1 , Years + N + 1 , 1 ); S[++top] = a[1]; for(int i = 2; i <= N; i++) { while( ( fabs(a[i].k - S[top].k) <= eps) || (top > 1 && X(a[i], S[top - 1]) <= X(S[top - 1], S[top]))) Ans[S[top].ID] = 0, top--; S[++top] = a[i]; } } int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else //freopen("bzoj_1007.in","r",stdin); //freopen("bzoj_1007.out","w",stdout); #endif N = read(); for(int i = 1; i <= N; i++) a[i].k = read(), a[i].b = read(), a[i].ID = i; sort(a + 1, a + N + 1); Solve(); for(int i = 1; i <= N; i++) if(Ans[i] == 1) printf("%d ",i); return 0; }