BZOJ 2732 二分+半平面相交 解题报告
来源:互联网 发布:力学软件 编辑:程序博客网 时间:2024/06/08 02:18
2732: [HNOI2012]射箭
Description
沫沫最近在玩一个二维的射箭游戏,如下图 1 所示,这个游戏中的 x 轴在地面,第一象限中有一些竖直线段作为靶子,任意两个靶子都没有公共部分,也不会接触坐标轴。沫沫控制一个位于(0,0)的弓箭手,可以朝 0 至 90?中的任意角度(不包括 0度和 90度),以任意大小的力量射出带有穿透能力的光之箭。由于游戏中没有空气阻力,并且光之箭没有箭身,箭的轨迹会是一条标准的抛物线,被轨迹穿过的所有靶子都认为被沫沫射中了,包括那些 只有端点被射中的靶子。这个游戏有多种模式,其中沫沫最喜欢的是闯关模式。在闯关模式中,第一关只有一个靶 子,射中这个靶子即可进入第二关,这时在第一关的基础上会出现另外一个靶子,若能够一箭 双雕射中这两个靶子便可进入第三关,这时会出现第三个靶子。依此类推,每过一关都会新出 现一个靶子,在第 K 关必须一箭射中前 K 关出现的所有 K 个靶子才能进入第 K+1 关,否则游戏 结束。沫沫花了很多时间在这个游戏上,却最多只能玩到第七关“七星连珠”,这让她非常困惑。 于是她设法获得了每一关出现的靶子的位置,想让你告诉她,最多能通过多少关
Input
输入文件第一行是一个正整数N,表示一共有N关。接下来有N行,第i+1行是用空格隔开的三个正整数xi,yi1,yi2(yi1 < yi2 ),表示第i关出现的靶子的横坐标是xi,纵坐标的范围是从yi1到yi2 。
输入保证30%的数据满足N≤100,50%的数据满足N≤5000,100%的数据满足N≤100000且给 出的所有坐标不超过109 。
Output
仅包含一个整数,表示最多的通关数。
Sample Input
5
2 8 12
5 4 5
3 8 10
6 2 3
1 3 7
Sample Output
3
【解题报告】
设这个经过原点的抛物线为y = a * x ^ 2 + b * x,设一条线段的起点和终点为(x0,y1)和(x0,y2),且y2 > y1。
将x0带入到设出的抛物线中,会得到y = a * x0 ^ 2 + b * x0,这时候需要满足的是y <= y2 && y >= y1,也就是a * x0 ^ 2 + b * x0 <= y2 && y1 <= a * x0 ^ 2 + b * x0
整理一下思路,x0,y1,y2是已知量,a和b是我们设出来的量,不妨换一种写法,令x = a,y = b,k = x0,那么原不等式组就是
=> x * k ^ 2 + y * k <= y2 && x * k ^ 2 + y * k >= y1
=> x * k ^ 2 + y * k - y2 <= 0 && x * k ^2 + y * k - y1 >= 0
这样就很明显了,不等式组化成了两个半平面,之后利用半平面交判定是否存在就可以了。最外层套一个二分,时间复杂度大概是O(nlog^2n)
然而
这道题玄学卡精度!!!
我花了40分钟各种调,最后把eps改成1e-50才过。。。
给出题人寄刀片!!!
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define N 200010struct Point{ long double x,y; Point(long double _ = .0,long double __ = .0):x(_),y(__) {} Point operator +(const Point &a)const { return Point(x+a.x,y+a.y); } Point operator -(const Point &a)const { return Point(x-a.x,y-a.y); } Point operator *(double a)const { return Point(x*a,y*a); } }p[N];struct Line{ Point p,v; long double alpha; Line(Point _,Point __):p(_),v(__) { alpha=atan2(v.y,v.x); }Line(){} bool operator <(const Line &a)const { return alpha<a.alpha; } }src[N],line[N],q[N];int t,lines;inline long double Cross(Point p1,Point p2) { return p1.x*p2.y-p1.y*p2.x; } inline bool OnLeft(Point p,Line l) { return Cross(l.v,p-l.p)>=0;//left or right} inline Point GetIntersection(Line l1,Line l2) { Point u=l1.p-l2.p; long double temp=Cross(l2.v,u)/Cross(l1.v,l2.v); return l1.p+l1.v*temp; } #define EPS 1e-50#define DCMP(a) (fabs(a)<EPS) inline bool HalfplaneIntersection(int lines) { int front=1,tail=1; q[1]=line[1]; for(int i=2;i<=lines;++i) { while(front<tail&&!OnLeft(p[tail-1],line[i])) --tail; while(front<tail&&!OnLeft(p[front],line[i])) ++front; if(DCMP(Cross(q[tail].v,line[i].v))) q[tail]=OnLeft(q[tail].p,line[i])?q[tail]:line[i]; else q[++tail]=line[i]; if(front<tail) p[tail-1]=GetIntersection(q[tail],q[tail-1]); } while(front<tail&&!OnLeft(p[tail-1],q[front])) --tail; return tail-front>1; } inline bool Judge(int mid){ mid<<=1; memcpy(line+1,src+1,sizeof(Line)*mid); sort(line+1,line+mid+1); return HalfplaneIntersection(mid); }int main(){ scanf("%d",&t); for(int i=1;i<=t;++i) { static double x,y1,y2; scanf("%lf%lf%lf",&x,&y1,&y2); src[++lines]=Line(Point(0,y2/x),Point(-1/x,1)); src[++lines]=Line(Point(0,y1/x),Point(1/x,-1)); } int l=1,r=t,ans=1; while(l<=r) { int mid=(l + r)>>1; if(Judge(mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); return 0;}
让我看到你们的双手
- BZOJ 2732 二分+半平面相交 解题报告
- bzoj 2732 射箭 半平面交 解题报告
- UVAlive 3890&Poj3525 半平面交+二分 解题报告
- BZOJ 1052 二分答案 解题报告
- bzoj 2732: [HNOI2012]射箭 (二分+半平面交)
- POJ3525/LA3890 Most Distant Point from the Sea 解题报告【计算几何】【二分答案】【半平面交】
- BZOJ 4443(SCOI2015)网络流+二分答案 解题报告
- BZOJ 2792 [POI 2012] 二分答案 解题报告
- BZOJ 1822 计算几何+网络流+二分答案 解题报告
- BZOJ 2527 [Poi 2011] 整体二分 解题报告
- BZOJ 1854 [Scoi 2010] 二分图 解题报告
- BZOJ 1562 [NOI 2009] 二分图 解题报告
- BZOJ 4950 [Wf 2017] 二分图最大匹配 解题报告
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告
- bzoj 4552 排序 线段树+二分 解题报告
- uva 1298 - Triathlon(二分+平面相交)
- bzoj 2732 [HNOI2012]射箭 半平面交(刘汝佳版不超时) + 整型二分处理
- 17.8.19 校内赛 解题报告【求线段交点+凸包+求多边形面积】【判定点是否在多边形内】【二分答案+半平面交】
- maven打包时将资源文件独立在jar包外
- java编程思想读书笔记九:接口
- 2017.5.27测试 2. 刷题(P1167)
- 中位数
- c++7
- BZOJ 2732 二分+半平面相交 解题报告
- 区间第k大 可修改主席树,树状数组套线段树。
- Java实现-落单的数3
- java语言当中-sleep()和await()的差异
- 学习树的概念和相关术语
- hdu4571
- BZOJ 3874: [Ahoi2014]宅男计划 三分+贪心
- 通过Android studio 关联 git 和Github 并用android studio把项目传到Github上
- Leetcode: Longest Palindrome