题面

BZOJ题面

思路

半平面交代码讲解戳这里,用的就是这道题

我们射箭的函数形如$y=Ax^2+Bx$

考虑每一个靶子$(x_0,y_1,y_2)$,实际上是关于$A,B$的不等式限制条件

我们只要求出有没有$(A,B)$满足所有$2*n$个限制条件就可以了

考虑一个限制条件$y_1\leq Ax_0^2+Bx_0\leq y_2$

把一个$x_0$除过去,可以得到$B$关于$A$的半平面两个:

$B\geq -x_0A+\frac{y_1}{x_0}$

$B\leq -x_0A+\frac{y_2}{x_0}$

实际上就是两条平行线(不过这个性质没什么用)

显然题目具有二分性,二分答案,每次对于前一部分的所有限制做半平面交即可

技巧

可以先把所有半平面(包括四个外围限制)排个序,然后每次二分求解的时候扫一遍提取出本次求解需要的

半平面交如果可以剩下一个点(本题是可以的),需要在判断点是否在线的右边的函数里面修改条件,不能包括点在线上的情况

半平面交模板参考这道题:所有线段有向,从a到b,半平面交求所有有向线段的左边半平面的交,外围框子是逆时针的

同一份半平面交里面的所有点线关系都是一致的(都是左边or右边)

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define eps 1e-18
#define inf 1e33
#define ll long long
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
inline bool sign(long double x){
if(x>eps) return 1;
if(x<-eps) return -1;
return 0;
}
int n,m;
struct node{
long double x,y;
node(long double xx=0.0,long double yy=0.0){x=xx;y=yy;}
inline friend node operator +(const node &a,const node &b){return node(a.x+b.x,a.y+b.y);}
inline friend node operator -(const node &a,const node &b){return node(a.x-b.x,a.y-b.y);}
inline friend node operator *(const node &a,const long double &b){return node(a.x*b,a.y*b);}
inline friend long double operator *(const node &a,const node &b){return a.x*b.y-a.y*b.x;}
inline friend long double operator /(const node &a,const node &b){return a.x*b.x+a.y*b.y;}
inline friend long double slope(const node &a,const node &b){return atan2l(a.y-b.y,a.x-b.x);}
}rt[300010];
struct seg{
node a,b;long double k;int id;
seg(node aa=node(),node bb=node()){a=aa;b=bb;k=slope(aa,bb);id=0;}
seg(node aa,node bb,long double kk){a=aa;b=bb;k=kk;id=0;}
inline friend bool operator <(const seg &a,const seg &b){return a.k<b.k;}
inline friend node cross(const seg &a,const seg &b){
long double v1=(a.a-b.b)*(a.b-b.b);
long double v2=(a.a-b.a)*(a.b-b.a);
return b.b+(b.a-b.b)*(v1/(v1-v2));
}
inline friend bool right(const node &a,const seg &b){
return ((a-b.b)*(a-b.a))>eps;
}
}lis[300010],a[300010],q[300010];
inline bool solve(int lim){
int i,head=1,tail=0,flag,tot=0;
for(i=1;i<=m;i++) if(lis[i].id<=lim) a[++tot]=lis[i];
for(i=1;i<=tot;i++){
flag=0;
while((head<=tail)&&(!sign(a[i].k-q[tail].k))){
if(right(q[tail].a,a[i])) tail--;
else{flag=1;break;}
}
if(flag) continue;
while(head<tail&&right(rt[tail],a[i])) tail--;
while(head<tail&&right(rt[head+1],a[i])) head++;
q[++tail]=a[i];
if(head<tail) rt[tail]=cross(q[tail],q[tail-1]);
}
while(head<tail&&right(rt[tail],q[head])) tail--;
while(head<tail&&right(rt[head+1],q[tail])) head++;
return (tail-head>1);
}
const long double pi=acos(-1.0);
int main(){
n=read();int i;long double x1,y1,y2;
m=n<<1;
for(i=1;i<=n;i++){
x1=read();y1=read();y2=read();
lis[i]=seg(node(0,y1/x1),node(1,y1/x1-x1));
lis[i+n]=seg(node(1,y2/x1-x1),node(0,y2/x1));
lis[i].id=lis[i+n].id=i;
}
lis[++m]=seg(node(-1e12,1e12),node(-1e12,-1e12),pi/2.0);
lis[++m]=seg(node(1e12,1e12),node(-1e12,1e12),0);
lis[++m]=seg(node(1e12,-1e12),node(1e12,1e12),-pi/2.0);
lis[++m]=seg(node(-1e12,-1e12),node(1e12,-1e12),pi);
sort(lis+1,lis+m+1);
int l=1,r=n,mid;
while(l<r){
mid=(l+r)>>1;mid++;
if(solve(mid)) l=mid;
else r=mid-1;
}
cout<<l<<'\n';
}

[HNOI2012][BZOJ2732] 射箭 [二分+半平面交]的更多相关文章

  1. 【BZOJ2732】【HNOI2012】射箭 二分+半平面交

    此题重点在卡精度!!! 本地已经下载数据测试并通过了,然而$B$站上还是$WA$的,可能是$CPU$对于$long\ double$ 的资瓷不一样. 此题答案显然是可以二分出来的,设当前要监测是否能射 ...

  2. UVa 1475 (二分+半平面交) Jungle Outpost

    题意: 有n个瞭望塔构成一个凸n边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包.在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来.输出敌人需要炸毁的数目. 分析: ...

  3. poj 3525Most Distant Point from the Sea【二分+半平面交】

    相当于多边形内最大圆,二分半径r,然后把每条边内收r,求是否有半平面交(即是否合法) #include<iostream> #include<cstdio> #include& ...

  4. 二分+半平面交——poj1279

    /* 二分距离,凸包所有边往左平移这个距离,半平面交后看是否还有核存在 */ #include<iostream> #include<cstring> #include< ...

  5. POJ3525:Most Distant Point from the Sea(二分+半平面交)

    pro:给定凸多边形,求凸多边形内的点到最近边界的最远距离. sol:显然是二分一个圆,使得圆和凸多边形不相交,但是这样很难实现. 由于是凸多边形,我们可以把二分圆转化为二分凸多边形的移动. 如果每一 ...

  6. POJ 3525/UVA 1396 Most Distant Point from the Sea(二分+半平面交)

    Description The main land of Japan called Honshu is an island surrounded by the sea. In such an isla ...

  7. POJ3525-Most Distant Point from the Sea(二分+半平面交)

    Most Distant Point from the Sea Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 3955   ...

  8. 【bzoj2732】[HNOI2012]射箭 二分+半平面交

    题目描述 给出二维平面上n个与y轴平行的线段,求最大的k,使得存在一条形如$y=ax^2+bx(a<0,b>0)$的抛物线与前k条线段均有公共点 输入 输入文件第一行是一个正整数N,表示一 ...

  9. poj3525Most Distant Point from the Sea(半平面交)

    链接 求凸多边形内一点距离边最远. 做法:二分+半平面交判定. 二分距离,每次让每条边向内推进d,用半平面交判定一下是否有核. 本想自己写一个向内推进..仔细一看发现自己的平面交模板上自带.. #in ...

随机推荐

  1. OpenCV 3.2 FlannBasedMatcher

    #include <iostream> #include <string> #include <boost/timer.hpp> #include "op ...

  2. nodejs 事件机制

    node 事件机制   一 三种定时器 NodeJS中有三种类型的定时器:超时时间.时间间隔.即时定时器 1.超时时间:setTimeout(callback,delayMilliSeconds,[a ...

  3. rn打包分析

    rn打包原来是packager,后来独立出一个专门的打包工具metro,构建工具的大体思路跟前端构建工具差不多,都会有一个启动文件,然后根据模块依赖关系把对应文件找到. 开发中打包 在开发中打包,我们 ...

  4. priority_queue(优先队列):排序不去重

    C++优先队列类似队列,但是在这个数据结构中的元素按照一定的断言排列有序. 头文件:#include<queue> 参数:priority_queue<Type, Container ...

  5. 三:QJM HDFS高可用

    本文介绍的是HDFS的一种HA方案.虽然有checkpoint node \backup node等,但是不能实现自动的failover. http://hadoop.apache.org/docs/ ...

  6. HADOOP docker(九):hdfs权限

    1. 概述2. 用户身份标识3. 组映射4.关于权限的实现5.文件系统API的变更6.应用程序shell的变更7.超级用户8.ACLs9.ACL 文件系统API10.ACL命令11.参数配置12.总结 ...

  7. 算法模板の数学&数论

    1.求逆元 int inv(int a) { ) ; return (MOD - MOD / a) * inv(MOD % a); } 2.线性筛法 bool isPrime[MAXN]; int l ...

  8. vue开发学习中遇到的问题以及解决方法

    1:node-sass 安装失败,可使用 cnpm 安装 npm install cnpm -g --registry=https://registry.npm.taobao.org cnpm -v ...

  9. 我的Vscode配置

    "editor.fontSize": 17,//字体大小 "editor.wordWrap": "on",//软换行 "files ...

  10. 《剑指Offer》题三十一~题四十

    三十一.栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的数字均不相等.例如,序列{1, 2, 3, 4 ,5}是某栈的压栈序列 ...