BZOJ 3170: [Tjoi2013]松鼠聚会

Description

有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

Input

第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-109<=x,y<=109

Output

表示为了聚会走的路程和最小为多少。

Sample Input

6

-4 -1

-1 -2

2 -4

0 2

0 3

5 -2

Sample Output

20

思路

对于这题,我们可以得到d(i,j)=max(|xi-xj|,|yi-yj|),
这是切比雪夫距离,可以与曼哈顿距离的转化,就是把(x,y)变为((x-y)/2,(x+y)/2)
然后求曼哈顿距离就可以了。可以 O(1) 的求出来每个点到其他所有点的距离,
前提是求了前缀和。
Xi*(i-1)-sum(1…i-1)+sum(i+1…n)-(n-i)*Xi

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 1000;
struct node
{
	long long x,y;	
}a[N];
long long sumx[N],sumy[N],x[N],y[N];
int n;
int main(){
	scanf("%d",&n);
	long long xx,yy;
	for(int i = 1; i <= n; i++){
		scanf("%lld%lld",&xx,&yy);
		a[i].x = (xx + yy); a[i].y = xx - yy;
		x[i] = a[i].x; y[i] = a[i].y;
	}
	sort(x+1,x+n+1); sort(y+1,y+n+1);
	for (int i = 1; i <= n; i++){
		sumx[i] += sumx[i-1] + x[i];
		sumy[i] += sumy[i-1] + y[i];
	}
	long long ans,pos,temp = 1e17;

	for (int i = 1; i <= n; i++){
		pos = lower_bound(x+1,x+n+1,a[i].x) - x;
		ans  = sumx[n] - sumx[pos] - sumx[pos] + (2*pos-n)*a[i].x;
		pos = lower_bound(y+1,y+n+1,a[i].y) - y;
		ans += sumy[n] - sumy[pos] - sumy[pos] + (2*pos-n)*a[i].y;
		temp  = min(temp,ans);
	}
	printf("%lld\n",temp>>1);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值