uva1475 Jungle Outpost

来源:互联网 发布:淘宝代评职称是真的吗 编辑:程序博客网 时间:2024/05/22 09:03

注意到我们并不需要知道总部到底建在哪,只需要求出至少删掉的点数就可以了。
因此可以二分答案,删掉的一定是一段连续的点,于是总共有O(n)种删法,每种删法对应一个半平面。判断交是否为空集即可。
因为得到的这些直线是有序的,并不需要每次额外排序,复杂度可以做到O(nlogn)

#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int maxn=200010;const double eps=1e-8;int cmp(double x){    if (x>eps) return 1;    if (fabs(x)<=eps) return 0;    return -1;}struct Vector{    double x,y;    Vector operator + (const Vector &v) const    {        return (Vector){x+v.x,y+v.y};    }    Vector operator - (const Vector &v) const    {        return (Vector){x-v.x,y-v.y};    }    Vector operator * (const double &k) const    {        return (Vector){x*k,y*k};    }    double ang() const    {        return atan2(y,x);    }}a[maxn],p[maxn];typedef Vector Point;double dot(Vector v,Vector u){    return v.x*u.x+v.y*u.y;}double cross(Vector v,Vector u){    return v.x*u.y-v.y*u.x;}struct Line{    Point p;    Vector v;    bool operator < (const Line &l) const    {        return cmp(v.ang()-l.v.ang())==-1;    }}f[maxn],t[maxn],que[maxn];bool onleft(Point p,Line l){    return cmp(cross(l.v,p-l.p))==1;}Point intersection(Line l1,Line l2){    Vector v=l1.p-l2.p;    double t=cross(l2.v,v)/cross(l1.v,l2.v);    return l1.p+l1.v*t;}int n;int ok(int k){    int hd,tl,x;    for (int i=1;i<=n;i++) t[i]=(Line){a[i+k+1],a[i]-a[i+k+1]};    for (int i=n+1;i<=2*n;i++) t[i]=t[i-n];    x=n+1;    for (int i=n+2;i<=2*n;i++)        if (t[i]<t[x]) x=i;    for (int i=1;i<=n;i++) f[i]=t[x-i+1];    que[hd=tl=1]=f[1];    for (int i=2;i<=n;i++)    {        while (hd<tl&&!onleft(p[tl-1],f[i])) tl--;        while (hd<tl&&!onleft(p[hd],f[i])) hd++;        if (!(que[tl]<f[i])&&!(f[i]<que[tl]))        {            if (!onleft(p[tl-1],f[i])) que[tl]=f[i];        }        else que[++tl]=f[i];        if (hd<tl) p[tl-1]=intersection(que[tl-1],que[tl]);    }    while (hd<tl&&!onleft(p[tl-1],que[hd])) tl--;    return tl-hd<=1;}void solve(){    int l,r,mid;    for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);    for (int i=n+1;i<=2*n+1;i++) a[i]=a[i-n];    l=1,r=n;    while (l<r)    {        mid=(l+r)/2;        if (ok(mid)) r=mid;        else l=mid+1;    }    printf("%d\n",l);}int main(){    //freopen("b.in","r",stdin);    while (scanf("%d",&n)==1) solve();}
原创粉丝点击