[中位数定理]

  • 的最小值,当等于的中位数时,取得最小值。即将升序排列后,

显然只与总坐标有关,即求,将升序排列后,当时值最小

总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;

void solve(){
    
    int n; cin >> n;
    vector<int> a(n + 10);
    for(int i = 1; i <= n; i ++){
        cin >> a[i] >> a[i];
    }
    sort(a.begin() + 1, a.begin() + 1 + n);
    int ans = 0;
    for(int i = 1; i <= n; i ++){
        ans += abs(a[i] - a[(n + 1) / 2]);
    }
    cout << ans << endl;
    return ;
}

signed main(){
    HelloWorld;

    int tt = 1; 
    while(tt --) solve();
    return 0;
}

题目二:https://www.luogu.com.cn/problem/P1632
由中位数定理可知如果将所有点移动到某点满足最小距离,则,其中,意思是一定是某一点的横左边以及某一点的纵左边,不一定是同一点,那么我就可以全部枚举横纵坐标:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;

const int inf = 1000000000000000000;
void solve(){
    int n; cin >> n;
    vector<int> x(n + 10), y(n + 10);
    for(int i = 1; i <= n; i ++) cin >> x[i] >> y[i];
    vector<int> pre(n + 10, inf); 
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            vector<int> dis;
            for(int k = 1; k <= n; k ++) dis.push_back(abs(x[k] - x[i]) + abs(y[k] - y[j]));
            sort(dis.begin(), dis.end());
            for(int i = 1; i < n; i ++) dis[i] += dis[i - 1];
            for(int i = 0; i < n; i ++) pre[i] = min(pre[i], dis[i]);
        }
    }
    for(int i = 0; i < n; i ++) cout << pre[i] << endl;
    return ;
}

signed main(){
    HelloWorld;

    int tt = 1; 
    while(tt --) solve();
    return 0;
}

题目三:https://www.luogu.com.cn/problem/P1889
  • 观察纵坐标,因为最终纵坐标一样,所以就是普通的中位数定理,即求
  • 再看横坐标,求的最小值,即求的最小值,这也可以使用中位数定理,令,那么求,首先对从升序排序,然后依次减去,满足“小减去小,大减去大”,这样使得整个序列趋向均匀,最后用中位数定理即可
总代码:
#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;

void solve(){
    
    int n; cin >> n;
    vector<int> x(n + 10), y(n + 10);
    for(int i = 1; i <= n; i ++) cin >> x[i] >> y[i];
    sort(x.begin() + 1, x.begin() + 1 + n);
    sort(y.begin() + 1, y.begin() + 1 + n);
    int ans = 0;
    for(int i = 1; i <= n; i ++){
        x[i] -= (i - 1);
        ans += abs(y[(n + 1) / 2] - y[i]);
    }
    sort(x.begin() + 1, x.begin() + 1 + n);
    for(int i = 1; i <= n; i ++) ans += abs(x[(n + 1) / 2] - x[i]);
    cout << ans << endl;
    return ;
}

signed main(){
    HelloWorld;

    int tt = 1; 
    while(tt --) solve();
    return 0;
}