• [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
  • 相关阅读:
    如何:在 DataGrid 控件中对数据进行分组、排序和筛选
    转载:一站式WPF依赖属性(DependencyProperty)
    转载:WPF 善用路由事件
    Tomcat内存溢出
    Postgresql允许远程访问配置修改
    python笔记2
    我怀念的
    OpenCV第二个assignment:检测QR code的3个 finder centers
    学期总结
    机器视觉课程的第一个assignment——OpenCV
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16482593.html
Copyright © 2020-2023  润新知