• BZOJ 2732 射箭


    http://www.lydsy.com/JudgeOnline/problem.php?id=2732

    题意:给你n个靶子,让你求是否有一个经过原点的抛物线经过最多的前k个靶子,求出最大的k

    思路:

    就是这样的形式:y1<=ax^2+bx<=y2,这里y1,y2,x是已知的,有多组,我们发现,变量只有a和b了,而且都是一次,这样就转换成二元一次不等式组,这个问题就是高二学过的线性规划了

    可以把它转换成半平面交,然后二分答案就可以了。

    坑点:TM BZOJ上面要用longdouble,不然会WA一发,还有,考试的时候我居然在二分里面排序,导致复杂度退化到nlog^2 n T_T,这点要记住了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define dou long double
     7 const dou inf=1e15;
     8 int tot,n;
     9 struct Point{
    10     dou x,y;
    11     Point(){}
    12     Point(dou x0,dou y0):x(x0),y(y0){}
    13 };
    14 struct Line{
    15     Point s,e;
    16     dou slop;
    17     int id;
    18     Line(){}
    19     Line(Point s0,Point e0):s(s0),e(e0){}
    20 }l[200005],c[200005],L[200005];
    21 int read(){
    22     int t=0,f=1;char ch=getchar();
    23     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    24     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    25     return t*f;
    26 }
    27 dou operator *(Point p1,Point p2){
    28     return p1.x*p2.y-p1.y*p2.x;
    29 }
    30 Point operator -(Point p1,Point p2){
    31     return Point(p1.x-p2.x,p1.y-p2.y);
    32 }
    33 bool cmp(Line p1,Line p2){
    34     if (p1.slop==p2.slop) return (p2.e-p1.s)*(p1.e-p1.s)>=0;
    35     else return p1.slop<p2.slop;
    36 }
    37 Point inter(Line p1,Line p2){
    38     dou k1=(p2.e-p1.s)*(p1.e-p1.s);
    39     dou k2=(p1.e-p1.s)*(p2.s-p1.s);
    40     dou t=(k2)/(k1+k2);
    41     dou x=p2.s.x+(p2.e.x-p2.s.x)*t;
    42     dou y=p2.s.y+(p2.e.y-p2.s.y)*t;
    43     return Point(x,y);
    44 }
    45 bool jud(Line p1,Line p2,Line p3){
    46     Point p=inter(p1,p2);
    47     return (p-p3.s)*(p3.e-p3.s)>0;
    48 }
    49 bool check(int mid){
    50     int Tot=0;
    51     for (int i=1;i<=tot;i++)
    52      if (l[i].id<=mid) L[++Tot]=l[i];
    53     int cnt=1;
    54     for (int i=2;i<=Tot;i++)
    55      if (L[i].slop!=L[i-1].slop) L[++cnt]=L[i]; 
    56     int ll=1,rr=2;
    57     c[1]=L[1];c[2]=L[2];
    58     for (int i=3;i<=Tot;i++){
    59         while (ll<rr&&jud(c[rr],c[rr-1],L[i])) rr--;
    60         while (ll<rr&&jud(c[ll],c[ll+1],L[i])) ll++;
    61         c[++rr]=L[i];
    62     } 
    63     while (ll<rr&&jud(c[rr],c[rr-1],c[ll])) rr--;
    64     while (ll<rr&&jud(c[ll],c[ll+1],c[rr])) ll++;
    65     if (rr-ll+1<3) return 0;
    66     else return 1;
    67 }
    68 int main(){
    69     n=read();
    70     l[++tot].s=Point(-inf,inf);l[tot].e=Point(-inf,-inf);
    71     l[++tot].s=Point(-inf,-inf);l[tot].e=Point(inf,-inf);
    72     l[++tot].s=Point(inf,-inf);l[tot].e=Point(inf,inf);
    73     l[++tot].s=Point(inf,inf);l[tot].e=Point(-inf,inf);
    74     for (int i=1;i<=n;i++){
    75         dou x=read(),y1=read(),y2=read();
    76         l[++tot].s.x=-1;l[tot].s.y=y1/x-(-1)*x;
    77         l[tot].e.x=1;l[tot].e.y=y1/x-x;
    78         l[tot].id=i;
    79         l[++tot].s.x=1;l[tot].s.y=y2/x-x;
    80         l[tot].e.x=-1;l[tot].e.y=y2/x+x;
    81         l[tot].id=i;
    82     }
    83     for (int i=1;i<=tot;i++) l[i].slop=atan2(l[i].e.y-l[i].s.y,l[i].e.x-l[i].s.x);
    84     std::sort(l+1,l+1+tot,cmp);
    85     int LL=1,RR=n,ans=0;
    86     while (LL<=RR){
    87         int mid=(LL+RR)>>1;
    88         if (check(mid)) ans=mid,LL=mid+1;
    89         else RR=mid-1;
    90     }
    91     printf("%d",ans);
    92 }
  • 相关阅读:
    手机端网页web开发要点
    js javascript:void(0) 真正含义
    牛客第二场 C.message(计算几何+二分)
    计算几何_三维凸包
    【kuangbin专题】计算几何_半平面交
    【kuangbin专题】计算几何_凸包
    【kuangbin专题】计算几何基础
    Codeforces 1058 D. Vasya and Triangle(分解因子)
    网络流模板
    2018 Multi-University Training Contest 6
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5638685.html
Copyright © 2020-2023  润新知