HDU 4311 - Meeting point-1(前缀和优化曼哈顿距离)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4311

题意:给定n个点,找出一点使得该点到其余各点的曼哈顿距离总和最小,输出最小值。

思路:分别对横纵坐标排序,比如说横坐标 x ,排好序后如果点 i 为所求,则前i-1个点的 x 坐标小于x[i]i+1 到 n 这 n-i 个点的 x 坐标大于x[i],则 x 轴对应的结果为(i-1)*x[i]-s[i-1]+s[n]-s[i]-(n-i)*x[i]s[i] 为前 i 个点的坐标值和。对 y 轴也做同样处理,枚举取出最大值即可。

#include 
using namespace std;
typedef long long ll;
typedef unsigned long long ul;
typedef pair pii;
typedef pair pli;
typedef pair pll;
#define mp make_pair
#define pb push_back
#define all(x) x.begin(), x.end()
#define bug prllf("*********\n")
#define debug(x) cerr<<#x<<" = "<<(x)< inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
const int N = 1e5 + 7;
int n;
ll s[N];
struct node
{
    ll x, y, sumx, sumy;
}a[N];
bool cmp1(node a, node b) {return a.x < b.x;}
bool cmp2(node a, node b) {return a.y < b.y;}
int main()
{
    IO; int T; cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 1; i <= n; i++)
            cin >> a[i].x >> a[i].y;
        memset(s, 0, sizeof s);
        sort(a + 1, a + 1 + n, cmp1);
        for(int i = 1; i <= n; i++)
            s[i] = s[i-1] + a[i].x;
        for(int i = 1; i <= n; i++)
            a[i].sumx = (i - 1) * a[i].x - s[i-1] + s[n] - s[i] - (n - i) * a[i].x;
        memset(s, 0, sizeof s);
        sort(a + 1, a + 1 + n, cmp2);
        for(int i = 1; i <= n; i++)
            s[i] = s[i-1] + a[i].y;
        for(int i = 1; i <= n; i++)
            a[i].sumy = (i - 1) * a[i].y - s[i-1] + s[n] - s[i] - (n - i) * a[i].y;
        ll ans = INF;
        for(int i = 1; i <= n; i++)
            ans = min(ans, a[i].sumx + a[i].sumy);
        cout << ans << '\n';
    }
}

 

你可能感兴趣的:(【欧拉回路/路径/曼哈顿距离】)