ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[luogu3222]射箭

2022-07-15 19:32:54  阅读:161  来源: 互联网

标签:队尾 ld 射箭 return Point operator const luogu3222


假设抛物线为$y=ax^{2}+bx$,二分枚举答案后,每个靶子的限制即半平面

换言之,问题即对这些半平面求交(是否为空),需注意$a\le 0$和$b\ge 0$的自身限制

关于半平面交,与凸包(指维护直线极值)类似,具体流程如下:

1.用点+向量的形式描述直线(规定其左侧为可行区域),并加入足够大的外边框

2.将所有直线按向量极角排序,并对同极角的直线仅保留最左侧的一条

3.维护一个队列,不断弹出队尾/队首,直至队尾/队首两直线交点在当前直线左侧

(注意:要优先处理队尾,反例即应仅保留队首时,若优先处理队首会仅保留队尾)

4.最终,不断弹出队尾,直至队尾两直线交点在队首左侧

时间复杂度为$o(n\log n)$(排序可以预处理),可以通过

另外,精度要求较高,以下代码仅供参考

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 200005
 4 #define eps 1e-18
 5 #define ld long double
 6 #define y1 y11
 7 int n,m,l,r,rk[N];ld x,y1,y2;
 8 struct Point{
 9     ld x,y;
10     Point operator + (const Point &k)const{
11         return Point{x+k.x,y+k.y};
12     }
13     Point operator - (const Point &k)const{
14         return Point{x-k.x,y-k.y};
15     }
16     Point operator * (const ld &k)const{
17         return Point{x*k,y*k};
18     }
19     ld operator * (const Point &k)const{
20         return x*k.y-y*k.x;
21     }
22 }P[N];
23 struct Line{
24     ld z;Point k,v;
25     Line(){}
26     Line(ld a,ld b,ld c){
27         if (fabsl(a)>eps)k=Point{c/a,0};
28         else k=Point{0,c/b};
29         z=atan2l(-a,b),v=Point{b,-a};
30     }
31     bool operator < (const Line &n)const{
32         if (fabsl(z-n.z)>eps)return z<n.z;
33         return (n.k-k)*v>0;
34     }
35 }a[N],q[N];
36 bool cmp(int x,int y){
37     return a[x]<a[y];
38 }
39 Point get_cross(Line x,Line y){
40     return x.k+x.v*(((y.k-x.k)*y.v)/(x.v*y.v));
41 }
42 bool check(int k){
43     l=1,r=0;
44     for(int i=1;i<=m;i++)
45         if (rk[i]<=k){
46             if ((l<=r)&&(fabsl(a[rk[i]].z-q[r].z)<eps))continue;
47             while ((l<r)&&((P[r]-a[rk[i]].k)*a[rk[i]].v)>0)r--;
48             while ((l<r)&&((P[l+1]-a[rk[i]].k)*a[rk[i]].v)>0)l++;
49             q[++r]=a[rk[i]];if (l<r)P[r]=get_cross(q[r],q[r-1]);
50         }
51     while ((l<r)&&((P[r]-q[l].k)*q[l].v)>0)r--;
52     return l+1<r;
53 }
54 int main(){
55     scanf("%d",&n);
56     a[++m]=Line(-1,0,0),a[++m]=Line(0,1,0);
57     a[++m]=Line(1,0,-1e9),a[++m]=Line(0,-1,-1e9);
58     for(int i=1;i<=n;i++){
59         scanf("%Lf%Lf%Lf",&x,&y1,&y2);
60         a[++m]=Line(x,1,y1/x),a[++m]=Line(-x,-1,-y2/x);
61     }
62     for(int i=1;i<=m;i++)rk[i]=i;
63     sort(rk+1,rk+m+1,cmp);
64     int l=0,r=n;
65     while (l<r){
66         int mid=(l+r+1>>1);
67         if (check((mid<<1)+4))l=mid;
68         else r=mid-1;
69     }
70     printf("%d\n",l);
71     return 0;
72 }
View Code

 

标签:队尾,ld,射箭,return,Point,operator,const,luogu3222
来源: https://www.cnblogs.com/PYWBKTDA/p/16482593.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有