洛谷3964 松鼠聚会

题目地址

p3964

解题思路

首先学习一下曼哈顿距离和切比雪夫距离即二者之间的转换。

那根据切比雪夫距离的定义,只要x, y这个点到它周围八个点的距离都是一的话,就是使用的切比雪夫距离。
对于给出的n个点,选择其中一个点并计算它到其他点的距离的话,由于切比雪夫距离定义为:d = max(|x1 - x2|,|y1 - y2|) 。计算所有点到当前点距离的时间复杂度为O(n)。那n个点就是O(n2)。时间上来说并不理想。
我们可以把给出的坐标转换为曼哈顿距离,曼哈顿距离的定义是 d = |x1 - x2| + |y1 - y2|。对于xi来说所有点到他的距离为 d = |x1 - xi| + |x2 - xi| + … + |xn - xi|
通过对所有点的x进行排序,就可以将公式里的绝对值去掉。
式子变为了 d = xi - x1 + xi - x2 +… + xi - xi + xi+1 - xi + … + xn - xi 也就是位置 i 之前的全变为xi减去当前点x值,i后面的全都不变。
再进行整理得到
在这里插入图片描述
进行一次遍历找到最小的距离即可,在转换的时候,可以先不除二,为了避免浮点数运算。在求出距离后再对距离除二即可。

参考博客:
https://blog.csdn.net/Code92007/article/details/103241897
https://www.cnblogs.com/adelalove/p/8612540.html
https://blog.csdn.net/qq_41997978/article/details/103213051?utm_source=app

AC代码

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

struct node
{
	ll x, y;
};

struct node a[100010];
ll x[100010], y[100010];
ll sumx[100010],sumy[100010];

int main()
{
	int n;
	
	cin >> n;
	
	for (int i=1; i<=n; i++)
	{
		cin >> x[i] >> y[i];
		a[i].x = x[i] + y[i];
		a[i].y = x[i] - y[i];
		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];
	}
	
	ll minnum = 8e18;
	
	for (int i=1; i<=n; i++)
	{
		int locationx = lower_bound(x+1, x+n+1, a[i].x) - x;
		int locationy = lower_bound(y+1, y+n+1, a[i].y) - y;
		ll temp = locationx * a[i].x - sumx[locationx] + (sumx[n] - sumx[locationx]) - (n-locationx)*a[i].x;
		temp += locationy * a[i].y - sumy[locationy] + (sumy[n] - sumy[locationy]) - (n - locationy) * a[i].y;
		minnum = min(minnum, temp);
	}
	
	cout << minnum / 2 << endl;
	
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值