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;
}