IAI 2022年5月丙组 T4 题解

这篇博客探讨了一种优化算法,用于解决在大量点集中找出曼哈顿距离最大的两个点的问题。原始暴力算法的时间复杂度为O(N^2),但通过对点的坐标进行特定转换并排序,可以将时间复杂度降低到O(n log n)。博客详细介绍了分类讨论和优化过程,并给出了AC代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

nnn 个点,每个点坐标为 (xi,yi)(x_i, y_i)(xi,yi)
要求我们其中找到两个点,使得这两个点之间的曼哈顿距离最大。

暴力求解

首先,我们想到一个暴力的算法。

LL maxx=0;
for (LL i=1; i<=n; i++) {
	for (LL j=1; j<=n; j++) {
		if (i==j) {
			//同一个点
			continue;
		}
		maxx = max(maxx, abs(x[i]-x[j])+abs(y[i]-y[j]);
	}
}

时间复杂度

很容易知道暴力的时间复杂度为 O(N2)O(N^2)O(N2)
由于本题的 nnn 相对比较大,达到 10510^5105 级别,因此这样的算法本题一定是 TLE。

优化算法

根据暴力的算法,我们知道需要优化部分就是 ∣xi−xj∣+∣yi−yj∣|x_i-x_j|+|y_i-y_j|xixj+yiyj
为了不失通用性,我们可以假设这两点就是 x1x_1x1x2x_2x2。那么本题就变为求 ∣x1−x2∣+∣y1−y2∣|x_1-x_2|+|y_1-y_2|x1x2+y1y2
我们分类讨论:

  1. x1>x2,y1>y2x_1>x_2, y_1> y_2x1>x2,y1>y2,变为 x1−x2+y1−y2→(x1+y1)+((−x2)+(−y2))x_1-x_2+y_1-y_2 \to (x_1+y_1)+((-x_2)+(-y_2))x1x2+y1y2(x1+y1)+((x2)+(y2))
  2. x1>x2,y1<y2x_1>x_2, y_1<y_2x1>x2,y1<y2,变为 x1−x2+y2−y1→(x1−y1)+((−x2)+y2)x_1-x_2+y_2-y_1 \to (x_1-y_1)+((-x_2)+y_2)x1x2+y2y1(x1y1)+((x2)+y2)
  3. x1<x2,y1>y2x_1<x_2, y_1>y_2x1<x2,y1>y2,变为 x2−x1+y1−y2→(−(x1)+y1)+(x2−y2)x_2-x_1+y_1-y_2 \to (-(x_1)+y_1)+(x_2-y_2)x2x1+y1y2((x1)+y1)+(x2y2)
  4. x1<x2,y1<y2x_1<x_2, y_1<y_2x1<x2,y1<y2,变为 x2−x1+y2−y1→((−x1)+(−y1))+(x2+y2)x_2-x_1+y_2-y_1 \to ((-x_1)+(-y_1))+(x_2+y_2)x2x1+y2y1((x1)+(y1))+(x2+y2)

通过观察上面的结果,我们发现,需要计算如下 444 个部分:x1+y1,x1−y1,−x1+y1,−x1−y1x_1+y_1, x_1-y_1, -x_1+y_1, -x_1-y_1x1+y1,x1y1,x1+y1,x1y1 即可。
也就是说,每次将一个点,分解为 444 个点。通过分别对 444 个方向点排序,这样最小值在下标为 111 的数组,最大值在下标为 nnn 的数组中。我们只需要计算一下这 444 个方向点的最大值即为答案。

AC 参考

#include <bits/stdc++.h>
using namespace std;
using LL=long long;
const int N=1e6+10;
LL a[6][N];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	LL n;
	cin>>n;
	for (LL i=1; i<=n; i++) {
		LL x,y;
		cin>>x>>y;
		a[1][i]=x+y;
		a[2][i]=-x+y;
		a[3][i]=x-y;
		a[4][i]=-x-y;
	}
	for (LL i=1; i<=4; i++) {
		sort(a[i]+1, a[i]+1+n);
	}

	LL maxx=0;
	for (LL i=1; i<=4; i++) {
		maxx=max(maxx, a[i][n]-a[i][1]);
	}
	cout<<maxx<<"\n";

	return 0;
}

时间复杂度

O(nlogn)O(nlogn)O(nlogn),也就是排序占用了最多的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值