题目描述
第一次看着道题的时候了解到了曼哈顿距离。
D1:两点之间的曼哈顿距离:横坐标的差的绝对值与纵坐标的差的绝对值之和。
其含义就是在只能横、竖走的情况下,从a点到b点要走多长
而题意就是:
D2:一个点到两条直线的曼哈顿距离:该点到两条直线上的所有点的曼哈顿距离中的最小值。
问题:n个点到两条线都有对应的曼哈顿距离,那么其中肯定有最大值;如果这两条线移动,这个最大值会变化。要求就是在坐标系上找出这两条直线,使得这个最大值最小。
思路:
因为两条直线垂直而且和分别与坐标轴成45°,所以如果我们把坐标轴旋转45°那么题意就变成了所有点到两条坐标轴的最小的曼哈顿距离,从网上了解到坐标轴距离转换公式:
在此不作推导,公式记住会用就好。博主是个菜鸡,,,
好了转换后坐标以后,我们可以想如果n个点要想得到最小的那么肯定越靠近中间所得的这N个点的曼哈顿距离的最大值越小,所以刚开始我的思路就是按X坐标排下序然后求中位数得到中间的X、Y坐标,可这样答案错误,很无解,然后就又换了种思路二分,二分0-1000000内的所有距离然后得到验证答案即可,重点还是在验证答案上面。
于是参考大佬的思路得到了:
因为这两条直线是垂直的,为了处理方便把坐标系逆时针旋转45度,然后这两个直线就是垂直于坐标轴的,接着把坐标按照x坐标从小到大排序,然后二分答案,对于每个二分的答案mid,按照x坐标从左到右枚举,直到找到最大的xj满足xj-xi<=mid2,在[i,j]区间内的点都在垂直线的范围内,剩下的[1,i-1]和[j+1,n]则属于水平线范围,如果满足在[1,i-1]和[j+1,n]找到最大y和最小y的差值<=mid2则把答案向更优二分,否则增大mid的值。
对于区间最大值最小值的我是用递推扫了一遍算的 ,当然也可以用RMQ计算,可总觉得RMQ好麻烦,没办法人家效率高呗,但是不知道为什么要找到xj-xi<=mid2的?可能是因为我们每次枚举的是Xi然后找离xi最大的距离xj有可能xi在我们二分的mid这段距离的中间,那么要找的就是mid,也有可能在mid这段距离的一段那么就是mid2,总之这道题还是需要花费时间去理解的,同时从这道题中学到了坐标转换,二分等等,还是挺不错的题,
代码
/*
Keep clam Believe youself
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<stack>
#include<set>
#include<cmath>
#define Xiaobo main
using namespace std;
const int maxn=2e5+7;
const int mod=1e9+7;
const double eps=1e-15;
const double pi=acos(-1);
const int INF=0x3f3f3f;
typedef long long ll;
ll read