atcoder abc179 E 题解

原题链接:abc179E

题目大意

在一个2D平面上有N个点,定义两个点之间的距离为曼哈顿距离,求最大距离的值.

数据范围

\(1 \leq n \leq 2e5\)

\(1 \leq x_i,y_i \leq 1e9\)

思路

由于\(n\)导致不能\(n^2\)肯定有什么压复杂度的办法,一个比较浅显的思路就是先对绝对值下手:先对\(x\)进行排序,对于当前考虑的\(x_i\)只考虑比他\(x\)更小的点\(j\)这样可以让一个绝对值\(|x_i - x_j|\)被拿掉,但是很明显\(y_i\)这部分还是没法做,因为两个信息并不是独立的,每个\(x_j\)拿出来做绝对值的运算虽然很好做,并且能直接地确定他们俩的贡献,但是没办法在此基础上快速找出最大的\(y\)能提供的贡献,因为信息不独立所以不能分开计算.

这里另外一种思路就是对表达式本身下手:

\(|x_i - x_j| + |y_i - y_j|\)

=\(\max(x_i - x_j,x_j - x_i) + \max(y_i - y_j,y_j - y_i)\)

=\(\max((x_i - x_j)+(y_i - y_j),(x_i - x_j)+(y_j - y_i),(x_j - x_i) +(y_i - y_j),(x_j - x_i)+(y_j - y_i))\)

合并一下相同的项,看一下是否有规律

=\(\max((x_i +y_i - (x_j +y_j),x_i - y_i - (x_j - y_j),-(x_i - y_i)+(x_j - y_j),-(x_i + y_i)+x_j +y_j))\)

这里我们可以发现第一个和第三个表达式互为相反数,第二个和第四个同理,可以转回绝对值表达式

=\(\max(|x_i + y_i - (x_j + y_j)|,|x_i - y_i - (x_j - y_j)|)\)

\(z_i = x_i + y_i,w_i = x_i - y_i\)

=\(\max(|z_i - z_j|,|w_i - w_j|)\)

到这里就可以直接把原来的问题进行转换了:

\(\max_{1 \leq i,j\leq n}(\max(|x_i - x_j| + |y_i - y_j|))\)

=\(\max\{\max_{1 \leq i,j \leq n}(|z_i - z_j|,|w_i - w_j|)\}\)

=\(\max\{(\max_{1 \leq i \leq n} z_i - \min_{1 \leq i \leq n} z_i),(\max_{1 \leq i \leq n} w_i - \min_{1 \leq i \leq n} w_i)\}\)

剩下的预处理出\(z_i,w_i\)的最大最小值就可以算出答案了,整体线性.

关于这种方法,本身转换这一步可以看做是把坐标旋转45°之后得到的,这样转换之后可以做的一个原因就是成功地把绝对值分离(把\(i\)\(j\)分离出去)了.

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 2e5+7;
pii p[N];
int z[N],w[N];
int main()
{
	int n;scanf("%d",&n);
    for(int i = 1;i <= n;++i)	scanf("%d%d",&p[i].x,&p[i].y);
    for(int i = 1;i <= n;++i)	z[i] = p[i].x + p[i].y,w[i] = p[i].x - p[i].y;
    
    int maxz = z[1],minz = z[1],maxw = w[1],minw = w[1];
    for(int i = 1;i <= n;++i)
    {
    	maxz = max(maxz,z[i]);
    	minz = min(minz,z[i]);
    	
    	maxw = max(maxw,w[i]);
    	minw = min(minw,w[i]);
    }
    printf("%d",max(maxz - minz,maxw - minw));
    return 0;
}

posted @ 2021-01-01 10:38  随处可见的阿宅  阅读(161)  评论(0编辑  收藏  举报