题解 P3964 【[TJOI2013]松鼠聚会】

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;
}
原文地址:https://www.cnblogs.com/colazcy/p/11800783.html