题意
给
n
n
n 个点,每个点坐标为
(
x
i
,
y
i
)
(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
(
N
2
)
O(N^2)
O(N2)。
由于本题的
n
n
n 相对比较大,达到
1
0
5
10^5
105 级别,因此这样的算法本题一定是 TLE。
优化算法
根据暴力的算法,我们知道需要优化部分就是
∣
x
i
−
x
j
∣
+
∣
y
i
−
y
j
∣
|x_i-x_j|+|y_i-y_j|
∣xi−xj∣+∣yi−yj∣。
为了不失通用性,我们可以假设这两点就是
x
1
x_1
x1 和
x
2
x_2
x2。那么本题就变为求
∣
x
1
−
x
2
∣
+
∣
y
1
−
y
2
∣
|x_1-x_2|+|y_1-y_2|
∣x1−x2∣+∣y1−y2∣。
我们分类讨论:
- x 1 > x 2 , y 1 > y 2 x_1>x_2, y_1> y_2 x1>x2,y1>y2,变为 x 1 − x 2 + y 1 − y 2 → ( x 1 + y 1 ) + ( ( − x 2 ) + ( − y 2 ) ) x_1-x_2+y_1-y_2 \to (x_1+y_1)+((-x_2)+(-y_2)) x1−x2+y1−y2→(x1+y1)+((−x2)+(−y2));
- x 1 > x 2 , y 1 < y 2 x_1>x_2, y_1<y_2 x1>x2,y1<y2,变为 x 1 − x 2 + y 2 − y 1 → ( x 1 − y 1 ) + ( ( − x 2 ) + y 2 ) x_1-x_2+y_2-y_1 \to (x_1-y_1)+((-x_2)+y_2) x1−x2+y2−y1→(x1−y1)+((−x2)+y2);
- x 1 < x 2 , y 1 > y 2 x_1<x_2, y_1>y_2 x1<x2,y1>y2,变为 x 2 − x 1 + y 1 − y 2 → ( − ( x 1 ) + y 1 ) + ( x 2 − y 2 ) x_2-x_1+y_1-y_2 \to (-(x_1)+y_1)+(x_2-y_2) x2−x1+y1−y2→(−(x1)+y1)+(x2−y2);
- x 1 < x 2 , y 1 < y 2 x_1<x_2, y_1<y_2 x1<x2,y1<y2,变为 x 2 − x 1 + y 2 − y 1 → ( ( − x 1 ) + ( − y 1 ) ) + ( x 2 + y 2 ) x_2-x_1+y_2-y_1 \to ((-x_1)+(-y_1))+(x_2+y_2) x2−x1+y2−y1→((−x1)+(−y1))+(x2+y2);
通过观察上面的结果,我们发现,需要计算如下
4
4
4 个部分:
x
1
+
y
1
,
x
1
−
y
1
,
−
x
1
+
y
1
,
−
x
1
−
y
1
x_1+y_1, x_1-y_1, -x_1+y_1, -x_1-y_1
x1+y1,x1−y1,−x1+y1,−x1−y1 即可。
也就是说,每次将一个点,分解为
4
4
4 个点。通过分别对
4
4
4 个方向点排序,这样最小值在下标为
1
1
1 的数组,最大值在下标为
n
n
n 的数组中。我们只需要计算一下这
4
4
4 个方向点的最大值即为答案。
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 ( n l o g n ) O(nlogn) O(nlogn),也就是排序占用了最多的时间。