bzoj2732 [HNOI2012]射箭
挺简单的一道半平面交的题。
对于每条线段$ax^{2}+bx \in [s,t] $,然后把a,b看成变量,每条线段就是两个半平面,注意抛物线开口向下,要限制一下a,b。
然后直接套板子就好了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #define N 200500 7 using namespace std; 8 struct point { 9 double x[2]; 10 point (){} 11 point (double a,double b){x[0]=a; x[1]=b;} 12 point operator + (point a){return point (x[0]+a.x[0],x[1]+a.x[1]);} 13 point operator - (point a){return point (x[0]-a.x[0],x[1]-a.x[1]);} 14 double operator * (point a){return x[0]*a.x[1]-x[1]*a.x[0];} 15 }p[N]; 16 struct line{ 17 point a,b; 18 double alp; 19 int id; 20 }l[N],q[N],tmp[N]; 21 int n,tot,bot,top; 22 inline void addline(line &l,point a,point b,int id){ 23 l.a=a;l.b=b;l.id=id; 24 l.alp=atan2(b.x[1]-a.x[1],b.x[0]-a.x[0]); 25 } 26 inline bool cmp(line a,line b){ 27 if(a.alp==b.alp) 28 return (b.a-a.a)*(b.b-a.a)>0; 29 return a.alp<b.alp; 30 } 31 inline bool judge(line c,line a,line b){ 32 point p; 33 double dot1=(b.a-a.a)*(b.b-a.a); 34 double dot2=(b.b-a.b)*(b.a-a.b); 35 p.x[0]=(a.a.x[0]*dot2+a.b.x[0]*dot1)/(dot1+dot2); 36 p.x[1]=(a.a.x[1]*dot2+a.b.x[1]*dot1)/(dot1+dot2); 37 return (c.b-p)*(c.a-p)>0; 38 } 39 inline bool check(int x){ 40 tot=0; 41 register int i,j; 42 for(i=1;i<=2*n+2;i++)if(l[i].id<=x) 43 tmp[++tot]=l[i]; 44 for(i=2,j=1;i<=tot;i++) 45 if(tmp[i].alp-tmp[j].alp>0) 46 tmp[++j]=tmp[i]; 47 tot=j; 48 bot=1;top=2; 49 q[1]=tmp[1];q[2]=tmp[2]; 50 for(i=3;i<=tot;i++){ 51 while(top>bot&&judge(tmp[i],q[top-1],q[top]))top--; 52 while(top>bot&&judge(tmp[i],q[bot+1],q[bot]))bot++; 53 q[++top]=tmp[i]; 54 } 55 while(top>bot&&judge(q[bot],q[top-1],q[top]))top--; 56 return top-bot>1; 57 } 58 int main(){ 59 scanf("%d",&n); 60 register int i; 61 double x,sy,ty; 62 point a,b; 63 for(i=1;i<=n;i++){ 64 scanf("%lf%lf%lf",&x,&sy,&ty); 65 a=point(0,sy/x),b=point(1,-x+sy/x); 66 addline(l[i*2-1],a,b,i); 67 a=point(0,ty/x),b=point(1,-x+ty/x); 68 addline(l[i*2],b,a,i); 69 } 70 addline(l[n*2+1],point(0,0),point(0,1),0); 71 addline(l[n*2+2],point(0,0),point(1,0),0); 72 sort(l+1,l+2*n+3,cmp); 73 int l=2,r=n,mid,ans=1; 74 while(l<=r){ 75 mid=(l+r)>>1; 76 if(check(mid))ans=mid,l=mid+1; 77 else r=mid-1; 78 } 79 printf("%d\n",ans); 80 return 0; 81 }
人生如梦亦如幻 朝如晨露暮如霞。