[HNOI2012] 射箭

本文详细解析了HNOI2012竞赛中的射箭题目,探讨了射箭过程中的物理原理、算法设计以及解题思路,帮助参赛者理解并掌握此类问题的解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<bits/stdc++.h>
#define mid ((l+r+1)>>1)
#define double long double
using namespace std;
const double eps=1e-15;
const double inf=1e15;
const int maxn=2e5+10;
int n,cnt=0;double X,Ya,Yb;
inline int sgn(double x){
	if(x>eps) return 1;
	if(x<-eps) return -1;
	return 0;
}
struct Grid{
	double x,y;
	Grid(double X=0,double Y=0){x=X,y=Y;}
	friend inline Grid operator+(const Grid &a,const Grid &b){return Grid(a.x+b.x,a.y+b.y);}
	friend inline Grid operator-(const Grid &a,const Grid &b){return Grid(a.x-b.x,a.y-b.y);}
	friend inline Grid operator*(const Grid &a,const double &b){return Grid(a.x*b,a.y*b);}
	friend inline Grid operator/(const Grid &a,const double &b){return Grid(a.x/b,a.y/b);}
	friend inline double cross(const Grid &a,const Grid &b){return a.x*b.y-a.y*b.x;}
}Qp[maxn<<1];typedef Grid Vector,Point;
struct Line{
	Point s,t;double Angle;int id;
	Line(Point S=Point(),Point T=Point()){s=S,t=T,Angle=atan2(t.y-s.y,t.x-s.x);}
	friend inline Point Intersection(const Line &a,const Line &b)
	{return a.s+(a.t-a.s)*cross(b.t-b.s,a.s-b.s)/cross(a.t-a.s,b.t-b.s);}
	friend inline bool Onright(const Line &a,const Point &b){return sgn(cross(a.t-a.s,b-a.s))<=0;}
	friend inline bool operator<(const Line &a,const Line &b){
		double R=a.Angle-b.Angle;
		if(sgn(R)!=0) return R<0;
		return sgn(cross(a.t-a.s,b.t-a.s))<0;
	}
}L[maxn<<1],l[maxn<<1],Ql[maxn<<1];
inline bool Half_Intersection(int x,int Head=0,int Tail=0){
	int i=1;while(L[i].id>x) ++i;
	for(Ql[0]=L[i++];i<=cnt;++i) if(sgn(L[i].Angle-L[i-1].Angle)!=0&&L[i].id<=x){
		while(Head<Tail&&Onright(L[i],Qp[Tail-1])) Tail--;
		while(Head<Tail&&Onright(L[i],Qp[Head]))   Head++;
		Ql[++Tail]=L[i];
		if(Head<Tail) Qp[Tail-1]=Intersection(Ql[Tail],Ql[Tail-1]);
	}
	while(Head<Tail&&Onright(Ql[Head],Qp[Tail-1])) Tail--;
	while(Head<Tail&&Onright(Ql[Tail],Qp[Head]))   Head++;
	return Tail-Head>1;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%Lf%Lf%Lf",&X,&Ya,&Yb);
		L[++cnt]=Line(Point(0,Ya/X),Point(1,Ya/X-X)),L[cnt].id=i;
		L[++cnt]=Line(Point(1,Yb/X-X),Point(0,Yb/X)),L[cnt].id=i;
	}
	L[++cnt]=Line(Point(-inf,eps),Point(-eps,eps)),L[cnt].id=0;
    L[++cnt]=Line(Point(-eps,eps),Point(-eps,inf)),L[cnt].id=0;
    L[++cnt]=Line(Point(-eps,inf),Point(-inf,inf)),L[cnt].id=0;
    L[++cnt]=Line(Point(-inf,inf),Point(-inf,eps)),L[cnt].id=0;
	sort(L+1,L+cnt+1);int l=1,r=n;
	while(l<r){
		if(Half_Intersection(mid)) l=mid;
		else r=mid-1;
	}printf("%d\n",l);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值