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 }