BZOJ 3210. 花神的浇花集会
首先按着固定套路,把切比雪夫距离转成曼哈顿距离:$(x,y)=(\frac {x+y} {2} , \frac {x-y} {2})$
当然代码实现时先不要除以 $2$ ,不然小数比较难受,最后统一除 $2$ 即可
然后可以用前缀和快速计算每个位置作为答案时的贡献
发现 $x$ 和 $y$ 可以单独考虑,所以分开枚举,这样复杂度就很 $ok$
然后写完发现样例都过不了....
分析一波发现,如果把转化后的坐标重新转回来,就有可能变成小数...
这就很有意思了,让我们回到原坐标系考虑一下
考虑对于 $x+y$ 相同的位置,并且 $x,y$ 均为整数那么 $x+1$ 就 $y-1$ ,所以对于 $x+y$ 相同的位置,$x-y$ 每次隔一个数
所以 $x+y$ 为偶数时 $x-y$ 必须为偶数,$x+y$ 为奇数时 $x-y$ 必须为奇数
所以我们只要分别处理一下 $x+y$ 为奇数时的最大值和为偶数时的最大值即可
注意转化后的坐标系内,我们的 $x,y$ 取值是在 $[-1e5,2e5]$
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; const ll INF=1e18; int n,x[N],y[N],bx[N],by[N]; ll sx[N],sy[N],ans[2]={INF,INF},Ans=INF; int main() { n=read(); int a,b; for(int i=1;i<=n;i++) { a=read(),b=read(); bx[i]=x[i]=a+b,by[i]=y[i]=a-b; } sort(bx+1,bx+n+1); sort(by+1,by+n+1); for(int i=1;i<=n;i++) sx[i]=sx[i-1]+bx[i]; for(int i=1;i<=n;i++) sy[i]=sy[i-1]+by[i]; for(int i=-100000;i<=200000;i+=2) { ll res=0; int p=lower_bound(bx+1,bx+n+1,i)-bx-1; res+=1ll*p*i-sx[p]; res+=sx[n]-sx[p]-1ll*(n-p)*i; ans[0]=min(ans[0],res); } for(int i=-99999;i<=199999;i+=2) { ll res=0; int p=lower_bound(bx+1,bx+n+1,i)-bx-1; res+=1ll*p*i-sx[p]; res+=sx[n]-sx[p]-1ll*(n-p)*i; ans[1]=min(ans[1],res); } for(int i=-100000;i<=200000;i++) { ll res=0; int p=lower_bound(by+1,by+n+1,i)-by-1; res+=1ll*p*i-sy[p]; res+=sy[n]-sy[p]-1ll*(n-p)*i; Ans=min(Ans,res+ans[(i%2+2)%2]); } printf("%lld\n",Ans/2); return 0; }