洛谷P3964 [TJOI2013]松鼠聚会

题链

题意:给定n个点,从中选择一个点poi,使得其他点到x的切比雪夫距离之和最小;

学习有关二维坐标系上有关曼哈顿距离与切比雪夫距离相互转化后;

可将题给求切比雪夫距离转化成求曼哈顿距离,相当于改变题意;

也就是说题意可变成 “ 给定n个点,从中选择一个点x,使得其他点到poi的曼哈顿距离之和最小 ”;

可通过枚举每一个点作为poi,求其他点到x的曼哈顿距离之和;

由于曼哈顿距离的性质,可将x方向上的坐标和y方向上的坐标分离,分别求其他点与poi的x方向上的贡献,y方向上的贡献,然后相加记录最小值;

计算贡献时可用前缀和维护减小复杂度;

#include <bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs rt<<1|1
#define LL long long
#define PI acos(-1.0)
#define eps 1e-8
#define Pair pair<double,double>
// notice
#define mod 998244353 
#define MAXN 1e18
#define MS 100009

LL n,m;
LL px[MS],py[MS]; 
LL gx[MS],gy[MS];
LL qzx[MS],qzy[MS];

int main() {
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i=1;i<=n;i++){
		LL x,y;
		cin >> x >> y;
		px[i] = gx[i] = x+y;
		py[i] = gy[i] = x-y;
	}
	sort(gx+1,gx+n+1);
	for(int i=1;i<=n;i++){
		qzx[i] = qzx[i-1] + gx[i];
	}
	sort(gy+1,gy+n+1);
	for(int i=1;i<=n;i++){
		qzy[i] = qzy[i-1] + gy[i];
	}
	LL ans = MAXN;
	for(int i=1;i<=n;i++){
		// 当前点在排序后的数组位置 
		LL xpos = lower_bound(gx+1,gx+n+1,px[i]) - gx;
		LL ypos = lower_bound(gy+1,gy+n+1,py[i]) - gy;
		// 比当前点小的x值贡献 + 比当前点大的x值贡献 
		LL xval = px[i]*xpos-qzx[xpos] + qzx[n]-qzx[xpos]-(n-xpos)*px[i];
		LL yval = py[i]*ypos-qzy[ypos] + qzy[n]-qzy[ypos]-(n-ypos)*py[i];
		ans = min(ans,xval+yval);
	}
	cout << ans/2 << "\n";
	

	return 0;
}

posted @ 2021-05-27 16:58  棉被sunlie  阅读(51)  评论(0)    收藏  举报