BZOJ1007: [HNOI2008] Horizontally visible line (monotonic stack)

Time Limit: 1 Sec  Memory Limit: 162 MB
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

3
-1 0
1 0
0 0

Sample Output

1 2

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;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325049739&siteId=291194637