博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2732[HNOI2012]射箭
阅读量:5021 次
发布时间:2019-06-12

本文共 2378 字,大约阅读时间需要 7 分钟。

题意:给出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
#include
#include
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
=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
>1; if(check(mid))l=mid+1; else r=mid-1; } printf("%d\n",l-1); return 0;}

 

转载于:https://www.cnblogs.com/liu-runda/p/6439792.html

你可能感兴趣的文章
Vim配置文件(Vimrc)
查看>>
RecyclerView 局部刷新(获取viewHolder 去刷新)
查看>>
PHP表单(get,post)提交方式
查看>>
使用vbs或者bat脚本修改IE浏览器安全级别和选项
查看>>
Silverlight入门
查看>>
Silverlight动态调用WEBSERVICE,WCF方法
查看>>
LeetCode 895. Maximum Frequency Stack
查看>>
模仿segmentfault 评论
查看>>
一个简单的日志函数C++
查看>>
Java 8 中如何优雅的处理集合
查看>>
IOS程序的启动过程
查看>>
连接Linux下 XAMPP集成环境中部署的禅道的数据库MariaDB
查看>>
Java操作Excel和Word
查看>>
Oracle 体系结构之ORACLE物理结构
查看>>
ORA-12538: TNS: no such protocol adapter
查看>>
盒子模型
查看>>
局域网协议
查看>>
[HNOI2012]永无乡 线段树合并
查看>>
Spring整合hibernate:3、使用XML进行声明式的事务管理
查看>>
SqlServer之Convert 函数应用格式化日期(转)
查看>>