SOLDIERS

有一个性质:在一个长为n的序列a中找一个数 \(a_k\) 使得 \(\sum\limits_{i=1}^n abs(a_i-a_k)\) 最小,则 \(a_k\) 是a的中位数。

于是在这题里,对于纵坐标直接找中位数,算一遍上面的式子即可。

横坐标稍加处理:先从小到大排序,此时数组的下标就是士兵最后从左到右的顺序。然后还是找中位数。但是每个士兵是从左到右站,而不是在一条直线上。后来想到把每个士兵的横坐标 \(x_i\) 减去i,这样士兵都在一条直线上,再套用上面的式子即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define int long long
const int N=10005;
int n,x[N],y[N],ans;
int labs(int t)
{
	return t>=0?t:-t;
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;++i)
		scanf("%lld%lld",&x[i],&y[i]);
	sort(x+1,x+n+1);
	for(int i=1;i<=n;++i)x[i]-=i;
	sort(x+1,x+n+1);
	sort(y+1,y+n+1);
	int mid=n/2+1;
	for(int i=1;i<=n;++i)
		ans+=labs(x[mid]-x[i])+labs(y[mid]-y[i]);
	printf("%lld\n",ans);
	return 0;
}

相关文章:

  • 2021-08-25
  • 2021-04-08
  • 2021-07-03
  • 2021-10-29
  • 2021-11-10
  • 2021-12-12
猜你喜欢
  • 2022-02-02
  • 2022-01-21
  • 2022-12-23
  • 2021-11-13
  • 2022-01-10
  • 2021-07-13
  • 2021-08-28
相关资源
相似解决方案