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 }
View Code

 

posted @ 2018-03-06 08:42  Ren_Ivan  阅读(251)  评论(0编辑  收藏  举报