Luogu-3222 [HNOI2012]射箭

几何题,二次函数,化一下式子吧

设二次函数\(y=ax^2+bx\),对于一个线段\((x,y1)\),\((x,y2)\),与他相交的条件是\(y1<=ax^2+bx<=y2\)

对于\(ax^2+bx>=y1\),可以化为变量为\(a,b\)的一次函数\(b>=xa+\frac{y1}{x}\),这可以表示成(a-b)平面上的一个半平面...

如果一些线段的半平面交不为空,就说明存在一条抛物线可以经过他们

二分答案判断,时间复杂度\(O(nlogn)\)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2e5+100;
struct Point{
    double x,y;
    Point(double xx=0,double yy=0){
        x=xx,y=yy;
    }
};
struct Vector{
    double x,y;
    Vector(double xx=0,double yy=0){
        x=xx,y=yy;
    }
};
struct Line{
    Point p;
    Vector v;
    double ang;
    int bh;
    Line(Point a=Point(),Vector b=Vector()){
        p=a,v=b;
        ang=atan2(v.y,v.x);
    }
}q[maxn],b[maxn],c[maxn];
int dcmp(double x){return fabs(x)<1e-17?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Vector operator * (double p,Vector a){return Vector(a.x*p,a.y*p);}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
double operator * (Point a,Point b){return a.x*b.y-a.y*b.x;}
bool operator < (Line x,Line y){return dcmp(x.ang-y.ang)==0?(dcmp(x.v*(y.p-x.p))>0):(x.ang<y.ang);}
Point glt(Line x,Line y){Vector v=x.p-y.p; return x.p+y.v*v/(x.v*y.v)*x.v;}
bool onright(Line a,Line b,Line t){Point p=glt(a,b); return dcmp(t.v*(p-t.p))<0;}
bool bpm(int x,int n,Line *b){
    int l=0,r=1,tot=0;
    for(int i=1;i<=n;i++)
        if(b[i].bh<=x){
            if(b[i].ang!=b[i-1].ang) tot++;
            c[tot]=b[i];
        }
    n=tot,q[0]=c[1],q[1]=c[2];
    for(int i=3;i<=n;i++){
        while(l<r&&onright(q[r],q[r-1],c[i])) r--;
        while(l<r&&onright(q[l],q[l+1],c[i])) l++;
        q[++r]=c[i];
    }
    while(l<r&&onright(q[r],q[r-1],q[l])) r--;
    while(l<r&&onright(q[l],q[l+1],q[r])) l++;
    return r-l>=2;
}
int n,m;
double x,sy,ty;
int main(){
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%lf%lf%lf",&x,&sy,&ty);
        b[++n]=Line(Point(0,sy/x),Vector(1,-x));
        b[n].bh=i;
        b[++n]=Line(Point(0,ty/x),Vector(-1,x));
        b[n].bh=i;
    }
    sort(b+1,b+n+1);
    int l=1,r=n+1,mid,ans;
    while(l<r){
        mid=l+r>>1;
        if(bpm(mid,n,b))
            ans=mid,l=mid+1;
        else
            r=mid;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nianheng/p/10013956.html