【总结】曼哈顿距离转切比雪夫距离

我们在用二维树状数组的时候,可以得到一个边与坐标轴平行的矩形内点集的信息。

如果我们需要得到得到到一个点的距离小于等于K的点的信息呢。这些点构成的不在是边也坐标轴平行的矩形,而是一个对角线与坐标轴平行的菱形。

可以通过转化,使得整个坐标轴旋转45°,然后我们菱形变成了方方正正的矩形,又可以用而二维树状数组或者直接用前缀和来得到矩形区间信息。

旋转后区域边长*√2,面积*2,原本的距离<=K的区域,现在变成了[x’-k,y’-k]到[x’+k,y’+k]的矩形区域。我们假设顺时针旋转45°。

怎么转化呢?为了避免用公式的时候出错,我们一竖一竖的旋转:

 

对于每一竖,我们得到(x,0)对应的(x,n-x+1),然后向上一个个移动,等效于向右上一个一个移动。

则有:

for(int i=1;i<=n;i++){
       int x=i,y=n-i+1;
       for(int j=1;j<=n;j++)
           b[x++][y++]=a[i][j];
}

注意, 为了避免K太大,而超出边界,而边界外的点没有可用信息,我们需要判断一下边界。

void stardard(int &x)
{
    x=max(x,1);
    x=min(x,2*n-1);
}

 所以想要得到信息的时候,也同样转化坐标:

int x1=x,y1=n-x+1;
    x1+=y-1;y1+=y-1;
int ans+=getSum(i,x1-k,y1-k,x1+k,y1+k);
里面记住缩小边界

那么根本不用记公式(虽然公式不难)。切比雪夫转曼哈顿的话,也只需要一个一个转就行了。不好处理边界的话,可以每个点的横纵坐标都加一个值,防止越界。

感觉还是比较常用的,所以例题就不说了。

原文地址:https://www.cnblogs.com/hua-dong/p/8278534.html