题意
给你若干个靶子
你可以完美地打出一个二次函数
问你最多可以穿过前面多少个靶子
题解
很容易想到二分答案
然后设这个二次函数是
y=ax2+bx
y
=
a
x
2
+
b
x
联系前面x个靶子可以得到若干个不等式
用半平面交判是否无解就可以了
一开始WA了。。改成long doubleT了。。
改回double,然后不知道又搞了什么就A了。。
CODE:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef double LB;
const int N=100005*2;
const LB eps=1e-18;
const LB MAX=1e9+5;
int n;
struct pnt
{
LB x,y;
pnt(){}
pnt(LB x1,LB y1) {x=x1;y=y1;}
};
struct qq
{
pnt x,y;
LB angle;
/* qq (){}
void print ()
{
printf("x:%lf %lf y:%lf %lf\n",x.x,x.y,y.x,y.y);
}*/
}s[N];int tot=0;
struct qr{LB l,r1,r2;}A[N];
void add (LB x1,LB y1,LB x2,LB y2)
{
tot++;
s[tot].x=pnt(x1,y1);
s[tot].y=pnt(x2,y2);
s[tot].angle=atan2(y2-y1,x2-x1);
}
void Ins (LB a,LB b,LB c)//ax+by<=c
{
if (abs(b)<-eps)
{
if (a>eps) add(c/a,0,c/a,1);
else add(c/a,1,c/a,0);
return ;
}
pnt x1=pnt(0,c/b),x2=pnt(1,(c-a)/b);
if (b>eps) add(1,(c-a)/b,0,c/b);
else add(0,c/b,1,(c-a)/b);
}
LB mul (pnt x,pnt y,pnt z)
{
LB x1=x.x-z.x,x2=y.x-z.x;
LB y1=x.y-z.y,y2=y.y-z.y;
return x1*y2-x2*y1;
}
bool cmp (qq x,qq y)
{
if (abs(x.angle-y.angle)<eps) return mul(x.y,y.y,x.x)<0;
return x.angle<y.angle;
}
pnt JD (qq x,qq y)
{
LB s1=mul(x.y,y.x,x.x);
LB s2=mul(y.y,x.y,x.x);
pnt xx;
xx.x=(y.x.x*s2+y.y.x*s1)/(s1+s2);
xx.y=(y.x.y*s2+y.y.y*s1)/(s1+s2);
return xx;
}
bool check (qq x,qq a,qq b)
{
pnt xx=JD(a,b);
return mul(x.y,xx,x.x)<-eps;
}
int q[N];
pnt ans[N];
int nn;
bool solve ()
{
sort(s+1,s+1+tot,cmp);
nn=1;
for (int u=2;u<=tot;u++)
if (s[u].angle-s[u-1].angle>eps)
s[++nn]=s[u];
tot=nn;
int st=1,ed=2;
q[1]=1;q[2]=2;
for (int u=3;u<=tot;u++)
{
while (st<ed&&check(s[u],s[q[ed]],s[q[ed-1]])) ed--;
while (st<ed&&check(s[u],s[q[st]],s[q[st+1]])) st++;
q[++ed]=u;
}
while (st<ed&&check(s[q[st]],s[q[ed]],s[q[ed-1]])) ed--;
while (st<ed&&check(s[q[ed]],s[q[st]],s[q[st+1]])) st++;
s[++ed]=s[st];
return ed-st>2;
}
bool check (int x)//前x个是不是都可以打中
{
tot=0;
add(0,0,0,1);
add(0,0,1,0);
add(-MAX,1,-MAX,0);
add(1,MAX,0,MAX); //printf("%d\n",tot);
for (int u=1;u<=x;u++)
{
Ins(-(A[u].l*A[u].l),-A[u].l,-A[u].r1);
Ins(A[u].l*A[u].l,A[u].l,A[u].r2);
}
/*for (int u=1;u<=tot;u++)
s[u].print();*/
return solve();
// printf("YES:%d\n",nn);
//return nn>2;
}
int main()
{
// freopen("input10.in","r",stdin);
scanf("%d",&n);
for (int u=1;u<=n;u++)
scanf("%lf%lf%lf",&A[u].l,&A[u].r1,&A[u].r2);
// printf("%d\n",n);
//check(1);
int l=1,r=n;
int ans=0;
while (l<=r)
{
int mid=(l+r)>>1;
// printf("%d %d %d\n",l,r,mid);
if (check(mid)) {ans=mid;l=mid+1;}
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}