zoukankan      html  css  js  c++  java
  • 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,jleq 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;
    }
    
    
  • 相关阅读:
    Windows环境下使用cygwin ndk_r9c编译FFmpeg
    android 开发环境搭建
    POJ 2559 单调栈入门,三种代码实现
    poj 2100 尺取法(尺度法)
    尺取算法 入门+模板+例题
    POJ 3579 Median 二分+思维
    POJ 3685 Matrix 二分套二分
    CodeForces 371C Hamburgers 二分
    HDU 4355 Party All the Time 三分算法
    HDU 3613 Best Reward Manacher算法
  • 原文地址:https://www.cnblogs.com/HotPants/p/14219540.html
Copyright © 2011-2022 走看看