• hdu 4311 & 4312 Meeting point 曼哈顿距离之和最小


    hdu 4311

    题意

    平面上(n(nleq 1e5))个点,找一个点到其它所有点的曼哈顿距离之和最小。

    思路

    如果是找一个坐标使得所有点到其曼哈顿距离之和最小,那么将(n)个横坐标排个序,取中间的一个为答案的横坐标,将(n)个纵坐标排个序,取中间的一个为答案的纵坐标。原因就是绝对值$$y=|x-a_1|+|x-a_2|+...+|x-a_n|$$的图像为平底锅型或者是尖底。因为可以在平面上任意取点,所以可以取最优的(x)(y).

    但是这道题并不能够任意取点,而是限定在了(n)个点中。怎么办呢?

    最常规的想法,就是将距离都算出来,取个最小值。然而直接算的话是(O(n^2))的,数据量显然不允许。那么就换种算的方法。

    还是先排序,考虑序列(a_1,a_2,...,a_n)(已升序排好),则$$|a_i-a_1|+|a_i-a_2|+...+|a_i-a_{i-1}|+|a_i-a_{i+1}|+...+|a_i-a_n|$$$$=((a_i-a_1)+(a_i-a_2)+...+(a_i-a_{i-1}))+((a_{i+1}-a_i)+...+(a_n-a_i))$$$$=(i-1)a_i-sum_{k=1}{i-1}a_k-(n-i)*a_i+sum_{k=i+1}{n}a_k$$$$=(2i-1-n)*a_i-sum_{k=1}{i-1}a_k+sum_{k=i+1}{n}a_k$$
    于是可以预处理前缀和后缀和,就可以在(O(n))的时间处理出来各个点对应的值了。

    最后每个点的横坐标距离和纵坐标距离加起来取个最小值即可。

    算法复杂度(O(nlogn)).

    Code

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f3f3f3f3f
    #define maxn 100010
    using namespace std;
    typedef long long LL;
    struct node {
        LL x, y;
    }a[maxn];
    bool cmp1(int i, int j) { return a[i].x < a[j].x; }
    bool cmp2(int i, int j) { return a[i].y < a[j].y; }
    LL x[maxn], y[maxn], pr[maxn], su[maxn];
    int id[maxn];
    void work() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%lld%lld", &a[i].x, &a[i].y);
        for (int i = 1; i <= n; ++i) id[i] = i;
    
        sort(id+1, id+1+n, cmp1);
        memset(pr, 0, sizeof pr);
        memset(su, 0, sizeof su);
        for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].x;
        su[n] = a[id[n]].x; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].x;
        for (int i = 1; i <= n; ++i) x[id[i]] = (2*i-1-n)*a[id[i]].x - pr[i-1] + su[i+1];
    
        sort(id+1, id+1+n, cmp2);
        memset(pr, 0, sizeof pr);
        memset(su, 0, sizeof su);
        for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].y;
        su[n] = a[id[n]].y; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].y;
        for (int i = 1; i <= n; ++i) y[id[i]] = (2*i-1-n)*a[id[i]].y - pr[i-1] + su[i+1];
    
        LL ans = inf;
        for (int i = 1; i <= n; ++i) ans = min(ans, x[i]+y[i]);
        printf("%lld
    ", ans);
    }
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) work();
        return 0;
    }
    
    

    hdu 4312

    题意

    平面上(n(nleq 1e5))个点,找一个点到其它所有点的切比雪夫距离之和最小。

    思路

    将切比雪夫距离转化为曼哈顿距离,方法为将坐标转45度。即将((x,y))的坐标映射为((x+y,y-x)).

    然后就可以直接套上一题了,最终答案除以2.

    Code

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f3f3f3f3f
    #define maxn 100010
    using namespace std;
    typedef long long LL;
    struct node {
        LL x, y;
    }a[maxn];
    bool cmp1(int i, int j) { return a[i].x < a[j].x; }
    bool cmp2(int i, int j) { return a[i].y < a[j].y; }
    LL x[maxn], y[maxn], pr[maxn], su[maxn];
    int id[maxn];
    void work() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            LL xx, yy;
            scanf("%lld%lld", &xx, &yy);
            a[i].x = xx+yy, a[i].y = yy-xx;
        }
        for (int i = 1; i <= n; ++i) id[i] = i;
    
        sort(id+1, id+1+n, cmp1);
        memset(pr, 0, sizeof pr);
        memset(su, 0, sizeof su);
        for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].x;
        su[n] = a[id[n]].x; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].x;
        for (int i = 1; i <= n; ++i) x[id[i]] = (2*i-1-n)*a[id[i]].x - pr[i-1] + su[i+1];
    
        sort(id+1, id+1+n, cmp2);
        memset(pr, 0, sizeof pr);
        memset(su, 0, sizeof su);
        for (int i = 1; i <= n; ++i) pr[i] = pr[i-1] + a[id[i]].y;
        su[n] = a[id[n]].y; for (int i = n-1; i > 0; --i) su[i] = su[i+1] + a[id[i]].y;
        for (int i = 1; i <= n; ++i) y[id[i]] = (2*i-1-n)*a[id[i]].y - pr[i-1] + su[i+1];
    
        LL ans = inf;
        for (int i = 1; i <= n; ++i) ans = min(ans, x[i]+y[i]);
        printf("%lld
    ", ans/2);
    }
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) work();
        return 0;
    }
    
    
  • 相关阅读:
    基于fis的前端模块化和工程化方案
    网页中font-family的属性解析
    centos 基础环境配置
    golang的各种数据格式的互相转换
    golang 的编译安装以及supervisord部署
    ip地址库选择
    golang中使用mongodb的操作类以及如何封装
    golang中使用mongodb
    golang使用sqlite
    centos 安装nginx
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/7659109.html
Copyright © 2020-2023  润新知