bzoj 3170 松鼠聚会 | 旋转坐标

来源:互联网 发布:des加密解密算法 f函数 编辑:程序博客网 时间:2024/03/28 17:56
这道题大意是选定一个点,使其它点到它的距离sigma(dis=max(x-x0,y-y0)) 最小。
做法是旋转坐标,横纵坐标分开统计每个点的答案,取最小值。
启示:
以前知道旋转坐标可以将dis=abs(x-x0)+abs(y-y0)的◇区域变成一个dis=max(x-x0,y-y0)的正方形区域,这道题让我知道了逆着做也是可以的。以后做坐标+距离的题都多想一想旋转坐标吧。
问题:
想到了之后,速敲了一个中位数,最后发现读错题了,不是可以在任意一点聚会。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 100010
using namespace std;
struct P { ll x,y,u,d,l,r;} p[N];
bool cmpx(P a,P b) { return a.x<b.x;}
bool cmpy(P a,P b) { return a.y<b.y;}
int main()
{
int n; ll ans=10000000000000000LL;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
ll x,y;
scanf("%lld%lld",&x,&y);
p[i].x=x+y; p[i].y=x-y;
}
int mid=(n+1)>>1;
sort(p+1,p+n+1,cmpx);
ll sum=0;
for (int i=1;i<=n;i++) p[i].u=p[i-1].u+(i-1)*abs(p[i].x-p[i-1].x);
for (int i=n;i;i--) p[i].d=p[i+1].d+(n-i)*abs(p[i].x-p[i+1].x);
sort(p+1,p+n+1,cmpy);
for (int i=1;i<=n;i++) p[i].l=p[i-1].l+(i-1)*abs(p[i].y-p[i-1].y);
for (int i=n;i;i--) p[i].r=p[i+1].r+(n-i)*abs(p[i].y-p[i+1].y);
for (int i=1;i<=n;i++) ans=min(ans,p[i].u+p[i].d+p[i].l+p[i].r);
printf("%lld\n",ans>>1);
return 0;
}



0 0