【bzoj3170】[Tjoi2013]松鼠聚会(数学题)
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3170
这道题要在n个点中求一个点使其他点到该点的切比雪夫距离最小。
有个结论:$ (x,y) -> ((x+y)/2,(x-y)/2) $:原坐标系中的切比雪夫距离=新坐标系中的曼哈顿距离。
$ (x,y)-> (x+y,x-y) $:原坐标系中曼哈顿距离=新坐标系中切比雪夫距离。
然后转坐标系,x,y坐标分开处理,前缀和搞一下就好了。
代码:
#include<cstdio> #include<algorithm> #define ll long long #define min(a,b) (a<b?a:b) #define maxn 100010 inline ll read() { ll x=0; char c=getchar(),f=1; for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=0; for(;'0'<=c&&c<='9';c=getchar())x=x*10+c-'0'; return f?x:-x; } struct data{ double x,y; int id; }a[maxn]; double sum[maxn],ansx[maxn],ansy[maxn]; int n; bool cmp1(data a,data b){return a.x<b.x;} bool cmp2(data a,data b){return a.y<b.y;} int main() { n=read(); for(int i=1;i<=n;i++){ int x=read(),y=read(); a[i].x=1.0*(x+y)/2; a[i].y=1.0*(x-y)/2; a[i].id=i; } std::sort(a+1,a+n+1,cmp1); sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].x; for(int i=1;i<=n;i++) ansx[a[i].id]=(a[i].x*(i-1)-sum[i-1])+(sum[n]-sum[i]-a[i].x*(n-i)); std::sort(a+1,a+n+1,cmp2); sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i].y; for(int i=1;i<=n;i++) ansy[a[i].id]=((a[i].y*(i-1)-sum[i-1])+(sum[n]-sum[i]-a[i].y*(n-i))); double mn=1ll<<60; for(int i=1;i<=n;i++) mn=min(mn,(ansx[i]+ansy[i])); printf("%.0lf\n",mn); }
另一道练习题:花神的浇花集会