首页 > 其他 > 详细

Luogu-3222 [HNOI2012]射箭

时间:2018-11-24 23:39:54      阅读:284      评论:0      收藏:0      [点我收藏+]

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

设二次函数\(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;
}

Luogu-3222 [HNOI2012]射箭

原文:https://www.cnblogs.com/nianheng/p/10013956.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!