bzoj 2732 射箭 半平面交

2732: [HNOI2012]射箭

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2531  Solved: 848
[Submit][Status][Discuss]

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 。

二分答案,发现是变成了形如ax^2+bx>y1,ax^1+bx<y2的不等式,把二次函数中的a和b当成x和y,求半平面交就行了。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #define N 210000
  7 #define eps 1e-10
  8 #define inf 1e15
  9 using namespace std;
 10
 11 int n;
 12
 13 struct point
 14 {
 15     double x,y;
 16     point(){};
 17     point(double _x,double _y)
 18     {
 19         x=_x;y=_y;
 20     }
 21 }p[N];
 22
 23 point operator - (point a,point b)
 24 {
 25     return point(a.x-b.x,a.y-b.y);
 26 }
 27
 28 point operator + (point a,point b)
 29 {
 30     return point(a.x+b.x,a.y+b.y);
 31 }
 32
 33 point operator * (point a,double b)
 34 {
 35     return point(a.x*b,a.y*b);
 36 }
 37
 38 point operator / (point a,double b)
 39 {
 40     return point(a.x/b,a.y/b);
 41 }
 42
 43 int dcmp(double x)//三态函数
 44 {
 45     if(fabs(x)<eps)return 0;
 46     if(x>eps)return 1;
 47     return -1;
 48 }
 49
 50 double cross(point a,point b)
 51 {
 52     return a.x*b.y-b.x*a.y;
 53 }
 54
 55 struct line
 56 {
 57     point p,v;
 58     int id;
 59     double ang;
 60     line(){};
 61     line(point pp,point vv,int _id)
 62     {
 63         p=pp;v=vv;
 64         ang=atan2(v.y,v.x);
 65         id=_id;
 66     }
 67     friend bool operator < (line aa,line bb)
 68     {
 69         return aa.ang<bb.ang;
 70     }
 71 }lines[N],deq[N*2];
 72
 73 point getpoint(line a,line b)
 74 {
 75     point u=a.p-b.p;
 76     double t=cross(b.v,u)/cross(a.v,b.v);
 77     return a.p+a.v*t;
 78 }
 79
 80 bool onright(point a,line b)
 81 {
 82     return cross(b.v,a-b.p)<0;
 83 }
 84 int tot,h,t;
 85 void insert(line l)
 86 {
 87     while(h<t&&onright(p[t-1],l))t--;
 88     while(h<t&&onright(p[h],l))h++;
 89     deq[++t]=l;
 90     if(h<t&&dcmp(deq[t].ang-deq[t-1].ang)==0)t--;
 91     if(h<t)p[t-1]=getpoint(deq[t],deq[t-1]);
 92 }
 93
 94 bool half(int cnt)
 95 {
 96     h=1;t=0;
 97     for(int i=1;i<=2*n+4;i++)
 98     {
 99         if(lines[i].id<=cnt)
100         {
101             insert(lines[i]);
102         }
103     }
104     while(h<t&&onright(p[t-1],deq[h]))t--;
105     return t-h>=2;
106 }
107
108 int main()
109 {
110     scanf("%d",&n);
111     lines[++tot]=line(point(inf,inf),point(-1,0),0);
112     lines[++tot]=line(point(-inf,inf),point(0,-1),0);
113     lines[++tot]=line(point(-inf,-inf),point(1,0),0);
114     lines[++tot]=line(point(inf,-inf),point(0,1),0);
115     for(int i=1;i<=n;i++)
116     {
117         double x,y1,y2;
118         scanf("%lf%lf%lf",&x,&y1,&y2);
119         lines[++tot]=line(point(0,y1/x),point(1,-x),i);
120         lines[++tot]=line(point(0,y2/x),point(-1,x),i);
121     }
122     sort(lines+1,lines+2*n+5);
123     int ha=1,ta=n;
124     while(ha<=ta)
125     {
126         int mid=(ha+ta)>>1;
127         if(half(mid))
128         {
129             ha=mid+1;
130         }
131         else ta=mid-1;
132     }
133     printf("%d\n",ta);
134     return 0;
135 }

时间: 2024-10-16 05:11:26

bzoj 2732 射箭 半平面交的相关文章

bzoj2732: [HNOI2012]射箭 半平面交

这题乍一看与半平面交并没有什么卵联系,然而每个靶子都可以转化为两个半平面. scanf("%lf%lf%lf",&x,&ymin,&ymax); 于是乎就有ymin<=ax^2+bx<=ymax.(因为抛物线一定经过点(0,0),所以c=0) 考虑前一个有ax^2+bx>=ymin  <=>  ax^2+bx-ymin>=0. #define A x^2 #define B x #define C ymin #define x

BZOJ 2732 HNOI 2012 射箭 半平面交

题目大意:给出一些与x轴垂直的线段,问一个经过原点的抛物线最多能按顺序经过多少条线段. 思路:总体上来说是数学题,我们来推一推. 设这个经过原点的抛物线为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

BZOJ 1137: [POI2009]Wsp 岛屿 半平面交

1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 165  Solved: 78[Submit][Status][Discuss] Description Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点.问

BZOJ 1038 ZJOI 2008 瞭望塔 半平面交

题目大意:给出一个村庄的轮廓,在这个村庄里可以在随意的地方建一个瞭望塔.这个塔须要足够高,使得可以看得村庄的全貌. 求这个瞭望塔的最小高度. 思路:对于村庄中的每一条边,瞭望塔为了看见它.必需要在这个直线左側的半平面区域.这种话为了满足全部的边的需求,做一次半平面交,瞭望塔的最高点必须在全部边的半平面交的区域内. 例如以下图例子. 全部边的半平面交区域就是上面的图形.设上面半平面的函数关系是F(x).村长的函数关系是G(x),那么问题就转化成了求一个x,使得(F(x) - G(x))最小. 这个

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,不然会W

HDU 2297 半平面交

Run Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 640    Accepted Submission(s): 181 Problem Description Since members of Wuhan University ACM Team are lack of exercise, they plan to particip

关于半平面交

嗯,这是一个很屌的东西.可以把他想象成数学中的线性规划问题,然后自然而然得想到就可以求最优解啦. 如何求解半平面交????? 做法一:暴力枚举点,用该点切割现有的凸多边形,这样的复杂度是O(n^2) 做法二:神奇的分治O(nlogn),然而我并不会.... 做法三:参见2006年朱泽园大神发明的排序增量法:这里就暂时不给详细介绍了. 复杂度O(nlogn),如果把快速排序改成基数排序,复杂度可以进一步降为:O(n)!!!!!! 半平面交的另外一个应用是求多边形的核:可以想象成站在一个多边形的点上

计算几何 半平面交

LA 4992 && hdu 3761 Jungle Outpost 杭电的有点坑啊..一直爆内存,后来发现大白的半平面交模板那里 point *p = new point[n]; line *q = new line[n]这里出了问题,应该是在函数里面申请不了比较大的数组,所以爆内存..我在全局定义了两个数组就不会爆了.. 本来跑了17s多的,后来半平面交sort( l, l + n ) 被我注释了,就跑了9s多,LA上跑了 2s..应该是输入数据比较好,不用按照极角排序..然后就是照着

POJ3525 半平面交

题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似二元函数的线性规划.如图 求半平面交:用的kuangbin模板= = sol:二分答案 二分距离值,按这个值把边界向内缩,再求新的半平面交.如图: 绿色的是原图形,蓝色是按距离值向里面缩进去之后得到的新图形.对这个新图做半平面交即可. 若半平面交存在,说明与边界的距离是该值的点存在(半平面交里面的点