LA4992 Jungle Post

题意

PDF

分析

炸连续的比炸单独的好。

二分答案,每种炸连续的构成一些半平面,判断半平面交是否为空。

时间复杂度\(O(T n \log^2)\)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0;
    rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>T read(T&x)
{
    return x=read<T>();
}
using namespace std;
typedef long long ll;

struct Point
{
    double x,y;
    
    Point(double x=0,double y=0)
    :x(x),y(y){}
};
typedef Point Vector;

Vector operator+(co Vector&A,co Vector&B)
{
    return Vector(A.x+B.x,A.y+B.y);
}

Vector operator-(co Vector&A,co Vector&B)
{
    return Vector(A.x-B.x,A.y-B.y);
}

Vector operator*(co Vector&A,double p)
{
    return Vector(A.x*p,A.y*p);
}

double Dot(co Vector&A,co Vector&B)
{
    return A.x*B.x+A.y*B.y;
}

double Cross(co Vector&A,co Vector&B)
{
    return A.x*B.y-A.y*B.x;
}

double Length(co Vector&A)
{
    return sqrt(Dot(A,A));
}

Vector Normal(co Vector&A)
{
    double L=Length(A);
    return Vector(-A.y/L,A.x/L);
}

double PolygonArea(vector<Point>p)
{
    int n=p.size();
    double area=0;
    for(int i=1;i<n-1;++i)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2;
}

struct Line
{
    Point P;
    Vector v;
    double ang;
    
    Line(Point P=0,Vector v=0)
    :P(P),v(v){ang=atan2(v.y,v.x);}
    
    bool operator<(co Line&L)co
    {
        return ang<L.ang;
    }
};

bool OnLeft(co Line&L,co Point&p)
{
    return Cross(L.v,p-L.P)>0;
}

Point LineLineIntersection(co Line&a,co Line&b)
{
    Vector u=a.P-b.P;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
    return a.P+a.v*t;
}

co double eps=1e-6;

vector<Point>HalfplaneIntersection(vector<Line>&L)
{
    int n=L.size();
    sort(L.begin(),L.end());
    
    int first,last;
    vector<Point>p(n);
    vector<Line>q(n);
    vector<Point>ans;
    
    q[first=last=0]=L[0];
    for(int i=1;i<n;++i)
    {
        while(first<last&&!OnLeft(L[i],p[last-1]))
            --last;
        while(first<last&&!OnLeft(L[i],p[first]))
            ++first;
        q[++last]=L[i];
        if(fabs(Cross(q[last].v,q[last-1].v))<eps)
        {
            --last;
            if(OnLeft(q[last],L[i].P))
                q[last]=L[i];
        }
        if(first<last)
            p[last-1]=LineLineIntersection(q[last-1],q[last]);
    }
    while(first<last&&!OnLeft(q[first],p[last-1]))
        --last;
    if(last-first<=1)
        return ans;
    p[last]=LineLineIntersection(q[last],q[first]);
    
    for(int i=first;i<=last;++i)
        ans.push_back(p[i]);
    return ans;
}

co int N=5e4;
int n;
Point P[N];

bool check(int m)
{
    vector<Line>lines;
    for(int i=0;i<n;++i)
        lines.push_back(Line(P[(i+m+1)%n],P[i]-P[(i+m+1)%n]));
    return HalfplaneIntersection(lines).empty();
}

int solve()
{
    if(n==3)
        return 1;
    int L=1,R=n-3,res;
    while(L<=R)
    {
        int M=(L+R)>>1;
        if(check(M))
            res=M,R=M-1;
        else
            L=M+1;
    }
    return res;
}


int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;++i)
        {
            read(P[i].x);read(P[i].y);
        }
        printf("%d\n",solve());
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10170542.html