[HNOI 2012] 射箭

把方程写出来就发现每一个限制条件都是相当于坐标轴上一条直线,然后半平面交,但是我nlog^2的程序会T而且T的那几个点如果把时限开大里面还会WA,大概被卡精度。我的代码只有70...这题比较好的方法是每次插入并判断吧类似WUY每次半平面交的方法.但是我懒得改了...


//By Richard
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#define rep(x,y,z) for (int x=(y);(x)<=(z);(x)++)
#define per(x,y,z) for (int x=(y);(x)>=(z);(x)--)
#define log2(x) (31-__builtin_clz(x))
#define mod (int)(1e9+7)
#define inf 0x3f3f3f3f
#define cls(x) memset(x,0,sizeof(x))
#ifdef DEBUG
#define debugdo(X) X
#define debugndo(X)
#define debugout(X) cout<<(#X)<<"="<<(X)<<endl
#else
#define debugdo(X)
#define debugndo(X) X
#define debugout(X)
#endif // debug
#ifdef ONLINE_JUDGE
#define debugdo(X)
#define debugndo(X)
#define debugout(X)
#endif
#define putarray(x,n) rep(iiii,1,n) printf("%d ",x[iiii])
#define mp make_pair
using namespace std;
typedef pair<int,int> pairs;
typedef long long LL;
const double eps=0.001,pi=3.1415926535897932384626433832795028841971693993751058209749446;
/read4.0
template <typename T>
inline void read(T &x){char ch;x=0;bool flag=false;ch=getchar();while (ch>'9'||ch<'0') {if (ch=='-') flag=true;ch=getchar();}while ((ch<='9'&&ch>='0')){x=x*10+ch-'0';ch=getchar();}if (flag) x*=-1;}
template <typename T>
inline void read(T &x,T &y){read(x);read(y);}
template <typename T>
inline void read(T &x,T &y,T &z){read(x);read(y);read(z);}
/variables&functions
const int maxn=222222;
struct Target
{
	double x,y1,y2;
}target;
int n,cnt;
struct Point
{
	double x,y;
	Point(double a=0,double b=0):x(a),y(b){}
	Point operator-(Point b)const{return Point(x-b.x,y-b.y);}
	double operator*(Point b)const{return x*b.y-y*b.x;}
};
#define angel angle
double mul(Point x,Point y,Point z){return (y.x-x.x)*(z.y-x.y)-(y.y-x.y)*(z.x-x.x);}
struct Line
{
	Point x,y;
	double angle;
	Line(Point a=Point(0,0),Point b=Point(0,0),double c=0):x(a),y(b),angle(c){}
	bool operator<(Line b)const{return (angle==b.angel)?mul(x,b.x,b.y)>0:angle<b.angle;}
	bool operator==(Line b)const{return angle==b.angle;}
}linee[maxn],line[maxn];
inline Point intersect(Line a,Line b)
{
	double k1=(b.y-a.x)*(a.y-a.x);
	double k2=(a.y-a.x)*(b.x-a.x);
	double k=k1/(k1+k2);
	return Point(b.y.x+(b.x.x-b.y.x)*k,b.y.y+(b.x.y-b.y.y)*k);
}
bool judgee(Line x,Line y,Line z)
{
	Point temp=intersect(x,y);
	return mul(temp,z.x,z.y)<0;
}
int deq[maxn],L,R,tot;
void hpi(Line *a,int n)
{
	sort(a+1,a+n+1);
	n=unique(a+1,a+n+1)-a-1;
	L=0,R=1;
	deq[0]=1;deq[1]=2;
	rep(i,3,n)
	{
		while (L<R&&judgee(a[deq[R-1]],a[deq[R]],a[i])) R--;
		while (L<R&&judgee(a[deq[L+1]],a[deq[L]],a[i])) L++;
		deq[++R]=i;
	}
	while (L<R&&judgee(a[deq[R-1]],a[deq[R]],a[deq[L]])) R--;
	while (L<R&&judgee(a[deq[L+1]],a[deq[L]],a[deq[R]])) L++;
	deq[++R]=deq[L];
}
bool judge(int n)
{
	rep(i,1,n*2) line[i]=linee[i];
	hpi(line,n*2);
	if (R-L>2) return true;
	return false;
}
double calc(double x,double y,double z)
{
	return z/y-x*y;
}
int main()
{
	//freopen("./2053/archery9.in","r",stdin);
	read(n);
	rep(i,1,n) 
	{
		read(target.x,target.y1,target.y2);
		linee[++cnt].y=Point(10,calc(10,target.x,target.y1));
		linee[cnt].x=Point(-10,calc(-10,target.x,target.y1));
		linee[cnt].angel=atan2(linee[cnt].x.x-linee[cnt].y.x,linee[cnt].x.y-linee[cnt].y.y);
		
		linee[++cnt].x=Point(10,calc(10,target.x,target.y2));
		linee[cnt].y=Point(-10,calc(-10,target.x,target.y2));
		linee[cnt].angel=atan2(linee[cnt].x.x-linee[cnt].y.x,linee[cnt].x.y-linee[cnt].y.y);
		// double temp1=target.y1/target.x;
		// if (abs(temp1)<eps) linee[++cnt]=Line(Point(1,temp1-target.x),Point(temp1/target.x,0),atan2(1-temp1/target.x,temp1-target.x));
		// else linee[++cnt]=Line(Point(0,temp1),Point(temp1/target.x,0),atan2(-temp1/target.x,temp1));
		// temp1=target.y2/target.x;
		// if (abs(temp1)<eps) linee[++cnt]=Line(Point(temp1-target.x,1),Point(0,temp1/target.x),atan2(temp1-target.x,1-temp1/target.x));
		// else linee[++cnt]=Line(Point(temp1/target.x,0),Point(0,temp1),atan2(temp1/target.x,-temp1));
	}
	int L=0,R=n;
	while (L<R)
	{
		int mid=(L+R)>>1;
		if (judge(mid)) L=mid+1;
		else R=mid;
		//debugdo(printf("%d %d\n",L,R));
	}
	printf("%d\n",L-1);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值