[TJOI2013]松鼠聚会

传送门

题意为给定一些点,选其中一个点使其他点到这个点的切比雪夫距离之和最小,求出最小距离。

切比雪夫距离= max ⁡ ( Δ x , Δ y ) \max(\Delta x,\Delta y) max(Δx,Δy),因为取 m a x max max不太好优化,我们可以把它转化为曼哈顿距离 ( Δ x + Δ y ) (\Delta x+\Delta y) (Δx+Δy)来做。

( x , y ) (x,y) (x,y)变为 ( x + y 2 , x − y 2 ) (\frac{x+y}2,\frac{x−y}2) (2x+y,2xy) 后,原坐标系中的切比雪夫距离 = = =新坐标系中的曼哈顿距离

( x , y ) (x,y) (x,y)变为 ( x + y , x − y ) (x+y,x−y) (x+y,xy)后,原坐标系中的曼哈顿距离 = = =新坐标系中的切比雪夫距离

如果 x , y x,y x,y数组都是有序的,那么

a n s x = ∑ j = 1 n Δ ( j , i ) ans_x=\sum ^{n}_{j=1}\Delta(j,i) ansx=j=1nΔ(j,i)

= Δ x ( 1 , i ) + Δ x ( 2 , i ) + Δ x ( 3 , i ) + . . . + Δ x ( n , i ) =\Delta x(1,i)+\Delta x(2,i)+\Delta x(3,i)+...+\Delta x(n,i) =Δx(1,i)+Δx(2,i)+Δx(3,i)+...+Δx(n,i)

= ( x i − x 1 ) + ( x i − x 2 ) + . . . + ( x i − x i − 1 ) + ( x i + 1 − x i ) + ( x i + 2 − x i ) + ( x n − x i ) =(x_i-x_1)+(x_i-x_2)+...+(x_i-x_{i-1})+(x_{i+1}-x_i)+(x_{i+2}-x_i)+(x_n-x_i) =(xix1)+(xix2)+...+(xixi1)+(xi+1xi)+(xi+2xi)+(xnxi)

= ∑ j = 1 i − 1 ( x i − x j ) + ∑ j = i + 1 n ( x j − x i ) =\sum_{j=1}^{i-1}(x_i-x_j)+\sum_{j=i+1}^n(x_j-x_i) =j=1i1(xixj)+j=i+1n(xjxi)

= ∑ j = 1 n x j − 2 × ∑ j = 1 i x j − x i × ( n − 2 × i ) =\sum_{j=1}^n x_j-2\times\sum_{j=1}^i x_j-x_i\times(n-2\times i) =j=1nxj2×j=1ixjxi×(n2×i)

然后就用前缀和优化一下

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){
	int x=0,f=1;char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=(x+(x<<2)<<1)+c-48;
	return x*f;
}
struct A{ll x,y;}a[N];ll x[N],y[N],s1[N],s2[N],ans=1ll<<62;int n,p,u,v;
int main(){
	n=read();
	for(int i=1;i<=n;++i) u=read(),v=read(),a[i].x=x[i]=u+v,a[i].y=y[i]=u-v;
	sort(x+1,x+n+1);sort(y+1,y+n+1);
	for(int i=1;i<=n;++i) s1[i]=s1[i-1]+x[i],s2[i]=s2[i-1]+y[i];
	for(int i=1;i<=n;++i){
        ll tmp=0;
        p=lower_bound(x+1,x+n+1,a[i].x)-x;tmp+=s1[n]-2*s1[p]-a[i].x*(n-2*p);
        p=lower_bound(y+1,y+n+1,a[i].y)-y;tmp+=s2[n]-2*s2[p]-a[i].y*(n-2*p);
        ans=min(ans,tmp);
	}return !printf("%lld",ans>>1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值