Description
给你(n)个点,坐标分别为((xi,yi))。从中取出三个点,使得其两两间曼哈顿距离和最大和最小,求最大值和最小值。
对于 100% 的数据, N<=100000 , 0<=Xi,Yi<=10^8
Solution
看完题目后感觉要分类讨论,思考1h后果断暴力O(n^3)。
但是判断了一下n<=500才跑暴力,得了30分。(™10^9过4s?不判50分)
其实可以O(n2)暴力的。(听说O(n2)+优化 = 100)
对于第一个最大值,我们可以(O(n))求出。
我们先扫一遍(n)个点,可以得到最大和最小的(x)以及最大和最小的(y)。
然后我们再枚举每个点,而其所组成的三个点的最大值便是(2 * max(maxx - a[i].x, a[i].x - minx) + 2 * max(maxy - a[i].y, a[i].y - miny))
因为它所组成的矩形是最长的长和最长的宽,所以值便是最大的。
这是运用了贪心的思想,可以感性理解一下。
然后我们再求最小值。
这里使用(O(n^2))的方法+优化的。
我们先将点按照(x)从小到大排序。
对于三个点:((x1, y1),(x2, y2),(x3, y3))。
(x1 < x2 < x3),所以关于(x)的答案就应该是:
((x2 - x1) + (x3 - x2) + (x3 - x1))
(=2 * (x3 - x1))
我们发现与(x2)无关。
所以我们只需枚举两个点,即可得到有关(x)的答案。
而(y)呢,我们便只需在线维护一个(i) ~ (j)的与(a[i].y,a[j].y)的差的最小值即可。
(if (a[j].x - a[i].x >= ans2) break;)
这个优化正确性显然。
Code
#include <cstdio>
#include <algorithm>
#define N 100010
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
struct node{int x, y;}a[N];
int n, m, maxy, miny, up, down, s, s1;
int ans1, ans2 = 2e9;
bool pd;
inline int read()
{
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x;
}
inline int cmp(node x, node y) {return x.x < y.x;}
inline int max(int x, int y) {return x > y ? x : y;}
inline int min(int x, int y) {return x < y ? x : y;}
int main()
{
freopen("bomb.in", "r", stdin);
freopen("bomb.out", "w", stdout);
n = read();
a[1].x = read();
maxy = miny = a[1].y = read();
fo(i, 2, n)
{
a[i].x = read(), a[i].y = read();
if (a[i].y > maxy) maxy = a[i].y;
else if (a[i].y < miny) miny = a[i].y;
}
sort(a + 1, a + n + 1, cmp);
ans1 = a[n].x - a[1].x + max(max(maxy - a[1].y, a[1].y - miny), max(maxy - a[n].y, a[n].y - miny));
fo(i, 2, n - 1) ans1 = max(ans1, max(a[n].x - a[i].x, a[i].x - a[1].x) + max(maxy - a[i].y, a[i].y - miny));
fo(i, 1, n)
{
if (n >= 10000 && pd && a[i].x == a[i - 1].x) continue;
if (a[i + 1].y < a[i].y) up = 2e9, down = a[i + 1].y;
else up = a[i + 1].y, down = -2e9;
pd = 0;
fo(j, i + 2, n)
{
if (a[j].x - a[i].x >= ans2) {pd = 1; break;}
s = max(up - a[i].y, abs(up - a[j].y));
s1 = max(a[i].y - down, abs(down - a[j].y));
s = max(min(s, s1), abs(a[i].y - a[j].y));
ans2 = min(ans2, a[j].x - a[i].x + s);
if (a[j].y < a[i].y) down = max(down, a[j].y);
else up = min(up, a[j].y);
}
}
printf("%d
%d
", ans1 << 1, ans2 << 1);
return 0;
}