两条直线(蓝桥杯)二分枚举+RMQ
给定平面上n个点。
求两条直线,这两条直线互相垂直,而且它们与x轴的夹角为45度,并且n个点中离这两条直线的曼哈顿距离的最大值最小。
两点之间的曼哈顿距离定义为横坐标的差的绝对值与纵坐标的差的绝对值之和,一个点到两条直线的曼哈顿距离是指该点到两条直线上的所有点的曼哈顿距离中的最小值。
第一行包含一个数n。
接下来n行,每行包含两个整数,表示n个点的坐标(横纵坐标的绝对值小于109)。
1 0
0 1
2 1
1 2
对于30%的数据,n<=100。
对于另外30%的数据,坐标范的绝对值小于100。
对于100%的数据,n<=105。
分析:因为这两条直线是垂直的,为了处理方便把坐标系逆时针旋转45度,然后这两个直线就是垂直于坐标轴的,接着把坐标按照x坐标从小到大排序,然后二分答案,对于每个二分的答案mid,按照x坐标从左到右枚举,直到找到最大的xj满足xj-xi<=mid*2,在[i,j]区间内的点都在垂直线的范围内,剩下的[1,i-1]和[j+1,n]则属于水平线范围,如果满足在[1,i-1]和[j+1,n]找到最大y和最小y的差值<=mid*2则把答案向更优二分,否则增大mid的值。
求区间内的最大值和最小值可以用RMQ来求,因为此题比较特殊,可以分别从左,和从右遍历一边从两端来记录最大值和最小值
#include"stdio.h"
#include"string.h"
#include"math.h"
#define M 100009
#include"vector"
#include"queue"
#include"stdlib.h"
#include"deque"
#define eps 1e-3
#define PI acos(-1.0)
#define inf 10000000000000LL
#include"algorithm"
using namespace std;
struct node
{
double x,y;
bool operator<(const node &p)const
{
return x<p.x;
}
}p[M];
int Log[M];
double maxl[M],minl[M],maxr[M],minr[M],val[M];
double dp_max[M][],dp_min[M][];
void initLog()
{
Log[]=-;
for(int i=;i<M;i++)
{
Log[i]=(i&(i-))==?Log[i-]+:Log[i-];
}
}
void RMQ(int n)
{
int m=Log[n];
for(int i=;i<=n;i++)
dp_max[i][]=dp_min[i][]=p[i].y;
for(int j=;j<=m;j++)
{
for(int i=;i<=n+-(<<j);i++)
{
dp_max[i][j]=max(dp_max[i][j-],dp_max[i+(<<(j-))][j-]);
dp_min[i][j]=min(dp_min[i][j-],dp_min[i+(<<(j-))][j-]);
}
}
}
double lcp_max(int l,int r)
{
int m=Log[r-l+];
return max(dp_max[l][m],dp_max[r+-(<<m)][m]);
}
double lcp_min(int l,int r)
{
int m=Log[r-l+];
return min(dp_min[l][m],dp_min[r+-(<<m)][m]);
}
double max(double a,double b)
{
return a>b?a:b;
}
double min(double a,double b)
{
return a<b?a:b;
}
node ver(node a)
{
double L=sqrt(a.x*a.x+a.y*a.y);
double du=asin(a.y/L);
du+=PI/;
a.x=L*cos(du);
a.y=L*sin(du);
return a;
}
//分别从两端记录最大值和最小值
void init(int n)
{
maxl[]=minl[]=p[].y;
for(int i=;i<=n;i++)
{
maxl[i]=max(p[i].y,maxl[i-]);
minl[i]=min(p[i].y,minl[i-]);
}
maxr[n]=minr[n]=p[n].y;
for(int i=n-;i>=;i--)
{
maxr[i]=max(p[i].y,maxr[i+]);
minr[i]=min(p[i].y,minr[i+]);
}
}
int judge(int n,double mid)
{
int left=,right=;
for(left=;left<=n;left++)
{
double up=-inf;
double down=inf;
while(right<=n&&p[right].x-p[left].x<=mid*)
{
right++;
}
if(left>)
{
up=max(up,lcp_max(,left-));
down=min(down,lcp_min(,left-));
}
if(right<=n)
{
up=max(up,lcp_max(right,n));
down=min(down,lcp_min(right,n));
}
if(up-down<=mid*)
return ;
}
return ;
}
int main()
{
int n;
initLog();
while(scanf("%d",&n)!=-)
{
for(int i=;i<=n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
p[i]=ver(p[i]);
}
sort(p+,p+n+);
double l=,r=max(p[n].x-p[].x,maxl[n]-minl[n]);
double mid;
//init(n);
RMQ(n);
while(fabs(r-l)>eps)
{
mid=(l+r)/;
if(judge(n,mid))
{
r=mid;
}
else
{
l=mid;
}
}
printf("%.1lf\n",r*sqrt(2.0));
}
return ;
}
两条直线(蓝桥杯)二分枚举+RMQ的更多相关文章
- 求空间内两条直线的最近距离以及最近点的坐标(C++)
关键词:空间几何 用途:总有地方会用到吧 文章类型:C++函数展示 @Author:VShawn(singlex@foxmail.com) @Date:2016-11-19 @Lab: CvLab20 ...
- 计算两条直线的交点(C#)
PS:从其他地方看到的源码是有问题的.下面是修正后的 /// <summary> /// 计算两条直线的交点 /// </summary> /// <param name ...
- 判断两条直线的位置关系 POJ 1269 Intersecting Lines
两条直线可能有三种关系:1.共线 2.平行(不包括共线) 3.相交. 那给定两条直线怎么判断他们的位置关系呢.还是用到向量的叉积 例题:POJ 1269 题意:这道题是给定四个点p1, ...
- POJ1269:Intersecting Lines(判断两条直线的关系)
题目:POJ1269 题意:给你两条直线的坐标,判断两条直线是否共线.平行.相交,若相交,求出交点. 思路:直线相交判断.如果相交求交点. 首先先判断是否共线,之后判断是否平行,如果都不是就直接求交点 ...
- poj 1269(两条直线交点)
Intersecting Lines Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 13481 Accepted: 59 ...
- CodeForces - 961D:Pair Of Lines (几何,问两条直线是否可以覆盖所有点)
You are given n points on Cartesian plane. Every point is a lattice point (i. e. both of its coordin ...
- C++ 根据两点式方法求直线并求两条直线的交点
Line.h #pragma once //Microsoft Visual Studio 2015 Enterprise //根据两点式方法求直线,并求两条直线的交点 #include"B ...
- C# 判断两条直线距离
本文告诉大家获得两条一般式直线距离 一般式的意思就是 Ax+By+C=0" role="presentation">Ax+By+C=0Ax+By+C=0 如果有两个 ...
- 2018-7-31-C#-判断两条直线距离
title author date CreateTime categories C# 判断两条直线距离 lindexi 2018-07-31 14:38:13 +0800 2018-05-08 10: ...
随机推荐
- Operand forms
Operand forms Computer Systems A Programmer's Perspective Second Edition
- Java程序设计的基本原则
Java程序设计的基本原则-1 1.面向对象 这是java编程里面大家公认的第一原则 2.优先使用对象组合而非类继承 3.分层 最典型的三层架构,表现层-->逻辑层-->数据层 表现层功能 ...
- TEST指令
In the x86 assembly language, the TEST instruction performs a bitwise AND on two operands. The flags ...
- css背景图片定位练习(二): background-position的百分比
background-position:x y; 百分比定位并不能直观的看出来,需要通过计算. background-position百分比计算公式: (容器宽度—背景图片的宽度)*x%=xpx(容器 ...
- 新的开始--Python
第一周——python基础 1.Python简介 1.1Python简史 1.2安装Python 1.3“hello world” 在运行第一个程序“hello world”之前,先来看看运行Pyth ...
- 有关sass
一.sass编译为css文件 编译的方法有很多 1.koala编译 请参考 http://www.w3cplus.com/blog/777.html http://koala-app.com/ind ...
- ecshop
if($cat_id == '205'){ $smarty->display('cat1.dwt', $cache_id); }elseif($cat_id == '2'){ $smarty-& ...
- 实现 UISegmentControl 与 UIScrollView的上下级联(分别在相应的方法中加入级联代码)
实现 UISegmentControl 与 UIScrollView的上下级联,需要在 [segmentCtr addTarget:self action:@selector(segmentedCon ...
- JS之相等操作符
1.相等 == 和不相等 != 先转换操作数再比较相等性 在转换不同的数据类型时,相等和不相等遵循以下规则: 1.1 如果有一个操作数是布尔值,则在比较相等性前先将其转换为数值---false转换为0 ...
- Windows7下 配置 Apache + PHP + MySQL + Zend Studio配置
相关软件下载: Apache 版本:(httpd-2.2.25) PHP ...