松鼠的聚会

description

有若干只松鼠住在可视为笛卡尔坐标系的草原上,它们想选定其中一只的家作为目的地去参加聚会,并且不希望走太长距离,请你求出最小距离.值得注意的是,一个点到其周围八个点距离均为$ 1 $.

solution

此题我们不难发现,任意两点间的距离为两点间横纵坐标差的绝对值的较大值,我们一般将这种距离叫做切比雪夫距离.其实,笛卡尔坐标系上两点(P_{1}(x_{1},y_{1}),P_{2}(x_{2},y_{2})),一共有三种距离,下面一一介绍.

第一种是我们最熟悉的笛卡尔距离,其表达式为(|P_{1}P_{2}|=sqrt{(x_{1}-x_{2})^{2}+(y_{1}-y_{2})^{2}})

第二种叫做曼哈顿距离,其表达式为(|P_{1}P_{2}|=|x_{1}-x_{2}|+|y_{1}-y_{2}|)

第三种比较少见,叫做切比雪夫距离,即本题要用到的.表达式如下:(|P_{1}P_{2}|=max(|x_{1}-x_{2}|,|y_{1}-y_{2}|))

特别的是,曼哈顿距离和切比雪夫距离可以互相转换.我们考虑最简单的情况,在一个二维坐标系中,设原点为(0,0)(0,0),如果用曼哈顿距离表示,则与原点距离为11的点会构成一个边长为11的正方形.image-20200806141651641

如果用切比雪夫距离表示,则与原点距离为11的点会构成一个边长为22的正方形

image-20200806141716731

第二个图像是由第一个图像放大两倍后旋转45°得到的.根据一堆神奇的性质我们可以(YY)出来,将图一中的点((x,y))对应图二中的点((frac{x+y}{2},frac{x-y}{2})),那么就可进行互化了.

于是乎我们可以将本题转化为曼哈顿距离,即求(Max_{i=1}^{n} { sum_{j ot= i}|x_{i}-x_{j}| +sum_{j ot= i}|y_{i}-y_{j}| }),去括号后利用前缀和维护,二分查找答案即可实现(Omicron(log n))一次查询.

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define R register
#define next MabLcdG
#define mod 1
#define debug puts("mlg")
#define Mod(x) ((x%mod+mod)%mod)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
inline ll read();
inline void write(ll x);
inline void writesp(ll x);
inline void writeln(ll x);
const ll maxn=310000;
ll n;
struct node{
	ll x,y;
}v[maxn];
ll sx[maxn],sy[maxn],lshx[maxn],lshy[maxn];
ll ans;
int main(){
	n=read();
	for(R ll i=1,x,y;i<=n;i++) x=read(),y=read(),v[i].x=lshx[i]=x+y,v[i].y=lshy[i]=x-y;
	sort(lshx+1,lshx+n+1);
	sort(lshy+1,lshy+n+1);
	for(R ll i=1;i<=n;i++) sx[i]=sx[i-1]+lshx[i],sy[i]=sy[i-1]+lshy[i];
	ans=((ull)1<<63)-1;
	for(R ll i=1;i<=n;i++){
		ll x=v[i].x,y=v[i].y;
		ll res=0;
		ll pos=lower_bound(lshx+1,lshx+n+1,x)-lshx;
		res+=pos*x-(n-pos)*x-sx[pos]+sx[n]-sx[pos];
		pos=lower_bound(lshy+1,lshy+n+1,y)-lshy;
		res+=pos*y-(n-pos)*y-sy[pos]+sy[n]-sy[pos];
		ans=min(ans,res);
	}	
	writeln(ans>>1);
}
inline ll read(){ll x=0,t=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') t=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*t;}
inline void write(ll x){if(x<0){putchar('-');x=-x;}if(x<=9){putchar(x+'0');return;}write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x);putchar(' ');}
inline void writeln(ll x){write(x);putchar('
');}
原文地址:https://www.cnblogs.com/ylwtsq/p/13446092.html