• bzoj2732[HNOI2012]射箭


    题意:给出n条y轴右侧的和y轴平行的线段,问用一条经过(0,0)开口向下且对称轴在y轴右侧的抛物线最多能贯穿多少条编号从1开始依次递增的线段.

    分析:首先有单调性,考虑二分答案转化为判定问题,那么记抛物线为y=ax^2+bx(a<0,b>0),每个线段对应两个关于a和b的二元一次不等式,也就是两个半平面,我们对当前需要打穿的靶子找出半平面,用半平面交求出(a,b)的可行域判断是否非空即可.因为a<0,b>0所以还要加包围框.

    然后…这数据好强….我WA了17次,好像不是最多的…最后面向数据debug了一波

    1.可行域可以是一个点或一个线段,这时也是有解的.我把靶子向上下各延长一点,这样点和线段就变成了多边形
    2.使用long double
    3.eps需要不断的尝试,不同的代码可能需要不同的eps,我最后是1e-18过的
    4.ax^2+bx必须满足a<0,b>0,需要在包围框中体现这个限制
    5.a,b不能等于0,所以包围框的坐标不能放在0,需要把包围框稍微移动一点,比如从0挪到-1e-13
    WA17次.....好像还不是最多的...

    要了数据...一个是原数据,一个是加强的一些边界数据

    http://files.cnblogs.com/files/liu-runda/%E5%8A%A0%E5%BC%BA%E7%9A%84%E6%95%B0%E6%8D%AE.zip 

    http://files.cnblogs.com/files/liu-runda/%E9%83%A8%E5%88%86%E5%8E%9F%E6%95%B0%E6%8D%AE.rar 

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const long double eps=1e-18;
    int cmp(long double x){return x<-eps?-1:x>eps;}
    const int maxn=300000;
    struct point{
      long double x,y;
      point(){}
      point(long double a,long double b){x=a;y=b;}
    }p[maxn];
    point operator +(const point &A,const point &B){return point(A.x+B.x,A.y+B.y);}
    point operator -(const point &A,const point &B){return point(A.x-B.x,A.y-B.y);}
    long double cross(const point &A,const point &B){return A.x*B.y-A.y*B.x;}
    struct line{
      point s,d;long double arg;line(){}
      line(point S,point D){s=S;d=D;arg=atan2(d.y,d.x);}
      bool operator <(const line &B)const{
        return cmp(arg-B.arg)==-1;
      }
    }L[maxn],q[maxn];
    long double x[maxn],Y1[maxn],Y2[maxn];
    int n,head,tail;
    point mult(long double t,point A){return point(A.x*t,A.y*t);}
    point intersect(line A,line B){
      long double t=cross(B.d,A.s-B.s)/cross(A.d,B.d);
      return A.s+mult(t,A.d);
    }
    bool toleft(line A,point B){
      return cmp(cross(A.d,B-A.s))>0;
    }
    bool HPI(){
      sort(L,L+n);
      head=tail=0;q[tail++]=L[0];
      for(int i=1;i<n;++i){
        while(head+1<tail&&!toleft(L[i],p[tail-2]))tail--;
        while(head+1<tail&&!toleft(L[i],p[head]))  head++;
        q[tail++]=L[i];
        if(head+1<tail&&cmp(cross(q[tail-1].d,q[tail-2].d))==0){
          tail--;
          if(toleft(q[tail-1],L[i].s))q[tail-1]=L[i];
        }
        if(head+1<tail)p[tail-2]=intersect(q[tail-1],q[tail-2]);
      }
      while(head+1<tail&&!toleft(q[head],p[tail-2]))tail--;
      p[tail-1]=intersect(q[head],q[tail-1]);
      /*
      bool flag=true;
      for(int i=head;i<tail;++i){
        if(cmp(p[i].x)!=0)flag=false;
      }
      if(flag)return false;*///printf("!");
      return tail-head>=3;
    }
    bool check(int ans){
      n=0;
      L[n++]=line(point(0,0),point(1e15,0));L[n++]=line(point(-1e-13,0),point(0,1e15));
      L[n++]=line(point(0,1e15),point(-1e15,0));L[n++]=line(point(-1e15,0),point(0,-1e15));//cha
      long double a,b,c1,c2;
      for(int i=1;i<=ans;++i){
        a=x[i]*x[i];b=x[i];c1=Y1[i];c2=Y2[i];
        L[n++]=line(point(0,c2/b),point(-1e3,1e3*a/b));L[n++]=line(point(0,c1/b),point(1e3,-1e3*a/b));
      }
      //  for(int i=0;i<n;++i)printf("(%f,%f)+(%f,%f)
    ",double(L[i].s.x),double(L[i].s.y),double(L[i].d.x),double(L[i].d.y));
      return HPI();
    }
    int main(){
      int n;scanf("%d",&n);
      int a,b,c;
      for(int i=1;i<=n;++i){
        scanf("%d%d%d",&a,&b,&c);x[i]=a;Y1[i]=b;Y2[i]=c;Y1[i]-=eps;Y2[i]+=eps;
      }
    
      int l=1,r=n;
      while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1;
        else r=mid-1;
      }
      printf("%d
    ",l-1);
      return 0;
    }
  • 相关阅读:
    XCTF EasyHook
    [GXYCTF2019]simple CPP
    [BJDCTF2020]ZJCTF,不过如此
    Open_basedir绕过
    P2240 【深基12.例1】部分背包问题
    PHP深浅拷贝
    关于_tostring[php]的另类利用
    通用Mapper常用方法
    @GetMapping、@PostMapping和@RequestMapping的区别
    IDEA 下载依赖包的问题
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6439792.html
Copyright © 2020-2023  润新知