排序+前缀和+切比雪夫转曼哈顿
如果本题给出的是曼哈顿距离,那么我们就可以按X和Y分别排序,求出前缀和,对于每个点O(1)判断找最佳答案。可是切比雪夫距离呢?也可以转化成曼哈顿距离!
先引入一个恒等式:
max(|a|,|b|)=|a+b2|+|a−b2|
可对a,b的正负性分类讨论进行证明
切比雪夫距离公式
d=max(|x1−x2|,|y1−y2|)
由上面恒等式变换可得
d=|(x1+y1)−(x2+y2)2|+|(x1−y1)−(x2−y2)2|
令 x′=x+y2,y′=x−y2
得
d=|(x′1)−(x′2)|+|(y′1)−(y′2)|
这是一个标准的曼哈顿距离公式,转换完毕。
即切比雪夫转曼哈顿(x,y)->((x+y)/2,(x-y)/2)
同理可证曼哈顿转切比雪夫(x,y)->(x+y,x-y)
#include<cstdio>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;
struct Point{ll x, y;}p[N];
ll sx[N], sy[N], x[N], y[N];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1, xx, yy; i <= n; i++)
{
scanf("%d%d",&xx,&yy);
p[i].x=x[i]=xx+yy;
p[i].y=y[i]=xx-yy;
}
sort(x+1,x+1+n);
sort(y+1,y+1+n);
for(int i = 1; i <= n; i++)
{
sx[i]=sx[i-1]+x[i];
sy[i]=sy[i-1]+y[i];
}
ll ans=1ll<<62;
for(int i = 1; i <= n; i++)
{
ll temp=0;
int pos;
pos=lower_bound(x+1,x+1+n,p[i].x)-x;
temp+=p[i].x*pos-sx[pos]+sx[n]-sx[pos]-(n-pos)*p[i].x;
pos=lower_bound(y+1,y+1+n,p[i].y)-y;
temp+=p[i].y*pos-sy[pos]+sy[n]-sy[pos]-(n-pos)*p[i].y;
ans=min(ans,temp);
}
printf("%lld\n",ans>>1);
}