bzoj 1007 计算几何,单调栈

1007: [HNOI2008]水平可见直线

tags:在纸上画画还是很容易看出的,可以看到的部分是一个半凸包,且随着交点横坐标增大时,直线斜率增加。所以这题只要按斜率排好序,再维护一个单调栈即可。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,b,a) for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define eps 1e-8
typedef long long ll;
const int N = 5e4+10;

struct Line{ int id; double a, b;
    friend bool operator < (const Line &a, const Line &b) {
        if(fabs(a.a-b.a)<eps) return a.b>b.b;
        return a.a<b.a;
    }
}line[N];
int n, top, Stack[N<<2], ans[N];
double solve(int i, int j)
{
    return (line[i].b-line[j].b)/(line[j].a-line[i].a);
}
int main()
{
    scanf("%d", &n);
    rep(i,1,n) {
        scanf("%lf %lf", &line[i].a, &line[i].b);
        line[i].id=i;
    }
    sort(line+1, line+1+n);
    rep(i,1,n) if((i>1 && fabs(line[i].a-line[i-1].a)>eps) || i==1) {
        while(true) {
            if(top<=1) { Stack[top++]=i; break; }
            int nd=Stack[top-2], st=Stack[top-1];
            double x1=solve(nd, st), x2=solve(st, i);
            if(x2<=x1) top--;
            else { Stack[top++]=i; break; }
        }
    }
    rep(i,0,top-1) ans[line[Stack[i]].id]=1;
    rep(i,1,n) if(ans[i]) printf("%d ", i);

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/6493355.html