UPD:(2019.11.6)修正了部分笔误
Solution [TJOI2013]松鼠聚会
题目大意:在(n)个点中找出一个点,使得其它所有点到它的切比雪夫距离和最小
切比雪夫距离,曼哈顿距离
分析:
首先在网格图中,如果走到一个点周围(8)个格子的代价都为(1)的话那么两点间的距离就是切比雪夫距离
然后关于切比雪夫距离和曼哈顿距离的相互转化
一个点在切比雪夫坐标系下的坐标为((x,y))的话,那么它在曼哈顿坐标系下的坐标就是((frac{x + y}{2},frac{x-y}{2}))
一个点在曼哈顿坐标系下的坐标为((x,y))的话,那么它在切比雪夫坐标系下的坐标就是((x+y,x-y))
所以此题我们可以把切比雪夫距离转化成曼哈顿距离来做,由于转化过程中可能出现浮点数导致精度误差,我们把所有点的坐标乘(2)最后除(2)即可
对于每个点按横纵坐标分别计算答案贡献即可
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
inline ll read(){
ll x = 0,f = 1;char c = getchar();
while(!isdigit(c))f = c == '-' ? -1 : f,c = getchar();
while(isdigit(c))x = x * 10 + c - '0',c = getchar();
return x * f;
}
struct Node{ll x,y,id;}val[maxn];
ll dis[maxn],sum[maxn],n,ans = 0x7fffffffffffffff;
inline ll query(int a,int b){return sum[b] - sum[a - 1];}
inline void getdis(){
sort(val + 1,val + 1 + n,[](const Node &a,const Node &b){return a.x < b.x;});
for(int i = 1;i <= n;i++)
sum[i] = sum[i - 1] + val[i].x;
for(int i = 1;i <= n;i++)
dis[val[i].id] += (ll)i * val[i].x - query(1,i),dis[val[i].id] += query(i + 1,n) - ll(n - i) * val[i].x;
sort(val + 1,val + 1 + n,[](const Node &a,const Node &b){return a.y < b.y;});
for(int i = 1;i <= n;i++)
sum[i] = sum[i - 1] + val[i].y;
for(int i = 1;i <= n;i++)
dis[val[i].id] += (ll)i * val[i].y - query(1,i),dis[val[i].id] += query(i + 1,n) - ll(n - i) * val[i].y;
}
int main(){
n = read();
for(int i = 1;i <= n;i++)val[i].x = read(),val[i].y = read(),val[i].id = i;
for(int i = 1;i <= n;i++){
ll nx = val[i].x + val[i].y,ny = val[i].x - val[i].y;
val[i].x = nx,val[i].y = ny;
}
getdis();
for(int i = 1;i <= n;i++)
ans = min(ans,dis[i]);
printf("%lld
",ans / 2);
return 0;
}