题目链接:
题意:给出n条第一象限内的竖直线段。求一个最大的K,使得某条经过原点的抛物线穿过前K条线段。
思路:设线段为(x,y1,y2),设抛物线为y=ax^2+b^x,那么有:y1<=ax^2+bx<=y2。据此可得到穿过该线段的抛物线参数a和b的两个方程,这两个方程是线性的。因此,可以半平面交,直到半平面内的点构不成多边形。
struct point{ double x,y; point(){} point(double _x,double _y) { x=_x; y=_y; } point operator+(point a) { return point(x+a.x,y+a.y); } point operator-(point a) { return point(x-a.x,y-a.y); } double operator*(point a) { return x*a.y-y*a.x; } point operator*(double t) { return point(x*t,y*t); } point operator/(double t) { return point(x/t,y/t); }};point a[2][N];int n,cnt[2],pre,cur;int sgn(double x){ if(x>EPS) return 1; if(x<-EPS) return -1; return 0; }int getDir(point p,point q,point a){ double t=(q-p)*(a-p); return sgn(t)>=0;}void add(point p){ a[cur][cnt[cur]++]=p;}point cross(point a,point b,point p,point q){ double s1=(a-p)*(b-p); double s2=(b-q)*(a-q); double t=s1+s2; return (p*s2+q*s1)/(s1+s2);}void cut(double k,double b,int isLeft){ point p=point(0,b),q=point(100,100*k+b); cnt[cur]=0; int i; a[pre][cnt[pre]]=a[pre][0]; point p1,q1; int x,y; FOR0(i,cnt[pre]) { p1=a[pre][i]; q1=a[pre][i+1]; x=getDir(p,q,p1)==isLeft; y=getDir(p,q,q1)==isLeft; if(x&&y) add(p1); else if(x) add(p1),add(cross(p,q,p1,q1)); else if(y) add(cross(p,q,p1,q1)); }}int main(){ RD(n); pre=0,cur=1; a[pre][0]=point(inf,0); a[pre][1]=point(inf,inf); a[pre][2]=point(-inf,inf); a[pre][3]=point(-inf,0); cnt[pre]=4; double x,y1,y2; int ans,i,flag=0; FOR1(i,n) { RD(x,y1,y2); if(flag) continue; ans=i; cut(-x,y1/x,1); swap(pre,cur); cut(-x,y2/x,0); swap(pre,cur); if(cnt[pre]<=2) ans=i-1,flag=1; } PR(ans);}