HYSBZ 3170 松鼠聚会

题意:
有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
题解:
①切比雪夫距离和曼哈顿距离之间的转化
②对于这题,我们可以得到dis(i,j)=max(|xi-xj|,|yi-yj|),
③设x'=(x+y)/2,y'=(x-y)/2,那么dis(i,j)=|xi'-xj'|+|yi'-yj'|


④x,y轴可以分开统计
⑤先是统计x轴,将所有松鼠的x'排序
用前缀和求出某个松鼠到其他松鼠的X轴距离之和:
(X[i]*(i-1)-sum[1~i-1]) + (sum[i+1~n]-(n-i)*X[i])
⑥y轴同理

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+10;
struct Node{
        int num;
        double x,y;
}a[maxn];
int n;
double sumX[maxn];
double sumY[maxn];
double ans=1e20;
bool cmpx(Node,Node);
bool cmpy(Node,Node);
void Prework();
void Query(int);
int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
                double x,y;
                scanf("%lf%lf",&x,&y);
                a[i].x=(x+y)/2,a[i].y=(x-y)/2;
        }
        Prework();
        for(int i=1;i<=n;i++)Query(i);
        printf("%.0f
",ans);
        return 0;
}
bool cmpx(Node A,Node B){
        return A.x<B.x;
}
bool cmpy(Node A,Node B){
        return A.y<B.y;
}
void Prework(){
        sort(a+1,a+1+n,cmpy);
        for(int i=1;i<=n;i++)
                sumY[i]=sumY[i-1]+a[i].y,a[i].num=i;
        sort(a+1,a+1+n,cmpx);
        for(int i=1;i<=n;i++)
                sumX[i]=sumX[i-1]+a[i].x;
}
void Query(int i){
        double tmp=0;
        tmp+=(sumX[i]-sumX[i-1])*(i-1)-sumX[i-1];
        tmp+=sumX[n]-sumX[i]-(n-i)*(sumX[i]-sumX[i-1]);
        int j=a[i].num;
        tmp+=(sumY[j]-sumY[j-1])*(j-1)-sumY[j-1];
        tmp+=sumY[n]-sumY[j]-(n-j)*(sumY[j]-sumY[j-1]);
        ans=min(ans,tmp);
}

原文地址:https://www.cnblogs.com/holy-unicorn/p/9510210.html