【题解】
很显然在一条坐标轴上到各个点距离之和最小的点就是它们的中位数。怎么证明呢?我们假设现在找的某个点x左边有a个点,右边有b个点(a>b)。我们把x向左移动d个单位,并保证x左边依然有a个点,右边依然有b个点,那么现在距离之和减小了ad-bd. 那也就是说,x左右的点数不一样,我们可以通过移动x找到更优的解。那么满足距离之和最小的x的左右两边的点数必须相等,中位数是满足这个条件的。
n维空间上的曼哈顿距离最小,就是把各个坐标轴分开考虑即可。
1 #include2 #include 3 #include 4 #define LL long long 5 #define rg register 6 #define N 1000010 7 using namespace std; 8 int n,mid,x[N],y[N],z[N]; 9 LL ans;10 inline int read(){11 int k=0,f=1; char c=getchar();12 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();13 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();14 return k*f;15 }16 int main(){17 n=read();18 for(rg int i=1;i<=n;i++) x[i]=read(),y[i]=read(),z[i]=read();19 sort(x+1,x+1+n); sort(y+1,y+1+n); sort(z+1,z+1+n);20 if(n&1){21 mid=x[(n+1)>>1];22 for(rg int i=1;i<=n;i++) ans+=abs(mid-x[i]);23 mid=y[(n+1)>>1];24 for(rg int i=1;i<=n;i++) ans+=abs(mid-y[i]);25 mid=z[(n+1)>>1];26 for(rg int i=1;i<=n;i++) ans+=abs(mid-z[i]);27 }28 else{29 mid=(x[n>>1]+x[(n>>1)+1])>>1;30 for(rg int i=1;i<=n;i++) ans+=abs(mid-x[i]);31 mid=(y[n>>1]+y[(n>>1)+1])>>1;32 for(rg int i=1;i<=n;i++) ans+=abs(mid-y[i]);33 mid=(z[n>>1]+z[(n>>1)+1])>>1;34 for(rg int i=1;i<=n;i++) ans+=abs(mid-z[i]);35 }36 printf("%lld\n",ans);37 return 0;38 }