学校模拟赛的题,我擦bzoj挂了只能手写对拍。。还好数据过了。
如果两点间距离是曼哈顿距离的话就直接前缀和搞定了,但是在本题中,dist(a,b)=max{|Xa-Xb|,|Ya-Yb|},实际上把坐标轴旋转45度之后就转化成了曼哈顿距离了。^_^。更加形象地,我们应该这么推导将原问题的距离转化成曼哈顿距离。
本题的距离:dist(a,b)=max{Xa-Xb, Ya-Yb, Yb-Ya, Xb-Xa}。
曼哈顿距离:dist(a,b)=max{Xa-Xb+Ya-Yb,Xa-Xb-Ya+Yb,-Xa+Xb+Ya-Yb,-Xa+Xb-Ya+Yb}
实际上,将上式的Xa变为下面的Xa+Ya,Ya变为下面的Xa-Ya,上式就变成下式辣!!>_<
于是,将原来的一个点{x,y},变成新的点{x',y'},同时使得{x'+y'=x;x'-y'=y},就可以用新的点跑辣!
时间复杂度O(NlogN)。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define N 200005
using namespace std;
int n; ll sum[N],ans[N]; struct node{ ll x,y; int id; }a[N];
bool cmpx(node aa,node bb){ return aa.x<bb.x; }
bool cmpy(node aa,node bb){ return aa.y<bb.y; }
int main(){
scanf("%d",&n); int i;
for (i=1; i<=n; i++){
scanf("%lld%lld",&a[i].x,&a[i].y);
a[i].x<<=1; a[i].y<<=1; a[i].id=i;
a[i].y=(a[i].x-a[i].y)/2; a[i].x-=a[i].y;
}
sort(a+1,a+n+1,cmpx);
for (i=1; i<=n; i++) sum[i]=sum[i-1]+a[i].x;
for (i=1; i<=n; i++)
ans[a[i].id]=a[i].x*i-sum[i]+sum[n]-sum[i]-a[i].x*(n-i);
sort(a+1,a+n+1,cmpy);
for (i=1; i<=n; i++) sum[i]=sum[i-1]+a[i].y;
for (i=1; i<=n; i++)
ans[a[i].id]+=a[i].y*i-sum[i]+sum[n]-sum[i]-a[i].y*(n-i);
for (i=2; i<=n; i++) ans[1]=min(ans[1],ans[i]);
printf("%lld\n",ans[1]>>1);
return 0;
}
by lych
2016.2.18