bzoj2732: [HNOI2012]射箭 半平面交

这题乍一看与半平面交并没有什么卵联系,然而每个靶子都可以转化为两个半平面。

scanf("%lf%lf%lf",&x,&ymin,&ymax);

于是乎就有ymin<=ax^2+bx<=ymax。(因为抛物线一定经过点(0,0),所以c=0)

考虑前一个有ax^2+bx>=ymin  <=>  ax^2+bx-ymin>=0。

#define A x^2

#define B x

#define C ymin

#define x' a

#define y' b

于是乎Ax'+By'+c>=0

这个式子貌似在哪见过的样子

于是乎上半平面交。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define pi (acos(-1.0))
 8 #define maxn 200100
 9 #define double long double
10 const long long inf=1e15;
11 int n,tot,sum;
12  
13 double sqr(double x){return x*x;}
14  
15 struct point{
16     double x,y;
17 }p[maxn];
18  
19 struct line{
20     point from,to;
21     int id;
22     double slope;
23 }l[maxn],q[maxn],a[maxn];
24  
25 point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
26 point operator +(point a,point b){return(point){a.x+b.x,a.y+b.y};}
27 double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
28 bool operator ==(line a,line b){return a.slope==b.slope;}
29 bool operator <(line a,line b){
30     return a.slope<b.slope||(a.slope==b.slope && (a.to-a.from)*(b.to-a.from)<0); 
31 }
32  
33 point getpoint(line a,line b){
34     double t1=(b.to-a.from)*(a.to-a.from),t2=(a.to-a.from)*(b.from-a.from);
35     double t=t1/(t1+t2);
36     return (point){(b.from.x-b.to.x)*t+b.to.x,(b.from.y-b.to.y)*t+b.to.y};
37 }
38  
39 bool check(line a,line b,line c){
40     point d=getpoint(a,b);
41     return (c.to-c.from)*(d-c.from)<0;
42 }
43  
44 bool bo(int x){
45     int cnt=0;
46     for (int i=1;i<=sum;i++) if (l[i].id<=x) a[++cnt]=l[i];
47     int head=1,tail=2;
48     q[1]=a[1],q[2]=a[2];
49     for (int i=3;i<=cnt;i++){
50         while (head<tail && check(q[tail-1],q[tail],a[i])) tail--;
51         while (head<tail && check(q[head+1],q[head],a[i])) head++;
52         q[++tail]=a[i];
53     }
54     while (head<tail && check(q[tail-1],q[tail],q[head])) tail--;
55     while (head<tail && check(q[head+1],q[head],q[tail])) head++;
56     return tail>head+1;
57 }
58  
59 int main(){
60     scanf("%d",&n);
61     l[++tot].to=(point){-inf,inf},l[tot].from=(point){inf,inf};
62     l[++tot].to=(point){inf,inf},l[tot].from=(point){inf,-inf};
63     l[++tot].to=(point){inf,-inf},l[tot].from=(point){-inf,-inf};
64     l[++tot].to=(point){-inf,-inf},l[tot].from=(point){-inf,inf};
65     for (int i=1;i<=n;i++){
66         double x,y1,y2;
67         scanf("%llf%llf%llf",&x,&y1,&y2);
68         double A=sqr(x),B=x,C=-y1;
69         l[++tot].from=(point){-1,(A-C)/B},l[tot].to=(point){1,(-A-C)/B},l[tot].id=i;
70         C=-y2;
71         l[++tot].from=(point){1,(-A-C)/B},l[tot].to=(point){-1,(A-C)/B},l[tot].id=i;
72     }
73      
74      
75     for (int i=1;i<=tot;i++) l[i].slope=atan2(l[i].to.y-l[i].from.y,l[i].to.x-l[i].from.x);
76     sort(l+1,l+tot+1);
77     sum=unique(l+1,l+tot+1)-l;
78     sum--;
79     int l=1,r=n;
80     while (l<=r){
81         int mid=(l+r)>>1;
82         if (bo(mid)) l=mid+1;
83         else r=mid-1;
84     }
85     printf("%d",r);
86     return 0;
87 }
View Code

 

posted @ 2016-08-06 08:36  DUXT  阅读(289)  评论(0编辑  收藏  举报