小结啥啊 很久之前写的 不过现在忘了 来复习一下 不过这种题 写暴力 也是很简单啊 但是分少啊qwq

1 欧式距离 也就是我们常说的 欧几里得距离 也就是 

$z=\sqrt{x^2+y^2}$ 然后也就是对应到平面上 求两个点的距离的时候 用横纵坐标之差 然后开根号 即可

就是 现在在班里学习文化课 的同学 数学课本上的 计算公式 很好理解 不过 这种一般用于 题目给定你是 这样计算距离 

至于 优化 我没见过什么 比较大的优化吧 或许 是我写题少

那么存在一个例题 就是奶酪qwq 奶酪好啊  题目

这里定义了一下 三维平面的计算公式 不过是多了一个维度z 此时距离 我们按照题目给定的计算方法 

显然 我们发现这是一个 并查集维护连通性的问题 那么怎么联通 一定是两个球体中心之间的距离 小于等于给定的 2*r 才能相切或者相交

由于我们发现开根号是此类问题的不好处理的地方 那么我们不妨考虑 此时两边平方 即可

#include<bits/stdc++.h>
typedef long long ll;
const ll N=1100;
ll T,n,h,r,x[N],y[N],z[N],father[N],d[N],u[N];
template<typename T>inline void read(T &x)
{
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x*=f;
}
inline long long dis(ll i,ll j) {
    return (ll)(x[i]-x[j])*(x[i]-x[j])+(ll)(y[i]-y[j])*(y[i]-y[j])+(ll)(z[i]-z[j])*(z[i]-z[j]); 
}
ll fa[N + 5];
ll find(ll x) {
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void Union(ll x, ll y) {
    fa[find(x)]=find(y);
}

signed main() {
    read(T);
    while(T--) {
        read(n);read(h);read(r);
        memset(x,0,sizeof(x));
        memset(y,0,sizeof(y));
        memset(z,0,sizeof(z));
        memset(u,0,sizeof(u));
        memset(d,0,sizeof(d));
        for(ll i=1;i<=n;++i) fa[i]=i; 
        for(ll i=1;i<=n;++i) read(x[i]), read(y[i]), read(z[i]);
        for(ll i=1;i<=n;++i)
            for(ll j=1;j<i;++j)
                if(dis(i,j)<=(ll)4*r*r)
                    Union(i,j);
        bool flag=0;
        for(ll i=1;i<=n;++i) {
            if(z[i]-r<=0) d[find(i)]=1;
            if(z[i]+r>=h) u[find(i)]=1;
        }
        for(int i=1;i<=n;++i)
        {
            if(d[i]&&u[i])flag=1;
            if(flag)break;
        }
        puts(flag ? "Yes" : "No");
    }
    return 0;
}

 


 

然后就要提到我们的曼哈顿距离了

定义曼哈顿距离是 

在二维空间内,两个点之间的曼哈顿距离为它们横坐标之差的绝对值与纵坐标之差的绝对值之和。

设点 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_02

java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_03

 

java 计算欧式距离公式 欧式距离算法简单解释_git_04

那么我们显然 发现一个东西 这玩意都是非负的 并且自己到自己是0呗(废话

并且 我们发现三个点之间的距离 存在一个三角不等式 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_05

java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_06

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_07

java 计算欧式距离公式 欧式距离算法简单解释_git_08

在国际象棋棋盘上,车从一个格子走到另一个格子的最短距离就是曼哈顿距离。

若网格图上的一个点只能到上下左右 java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_09

 


 

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_10

让你求 若干点对 求 曼哈顿距离 最大的 点对 n是5e4的

根据题意,对于式子$d(A,B) = \left | x_1 - x_2\right | + \left | y_1 - y_2 \right |$java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_11

第一种情况:java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_12

java 计算欧式距离公式 欧式距离算法简单解释_git_13

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_14

java 计算欧式距离公式 欧式距离算法简单解释_git_15

java 计算欧式距离公式 欧式距离算法简单解释_git_16

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_17

第四种情况  java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_18

那么他们之间的距离 就是 x2-x1+y2-y1=(x2+y2)- (x1+y1)

那么 我们不免发现 距离

要么 之和 x+y 有关 要么 只和 x-y 有关 那么答案就是

max{max{xi+yi}−min{xi+yi},max{xi−yi}−min{xi−yi}}

#include<bits/stdc++.h>
using namespace std;
int n,x,y;
template<typename T>inline void read(T &x)
{
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x*=f;
}
const int N=(1<<30);
int max1=-N,max2=-N,min1=N,min2=N;
int main() {
    read(n);
    for(int i=1;i<=n;i++) {
        read(x); read(y);
        max1=max(max1,x+y); min1=min(min1,x+y);
        max2=max(max2,x-y); min2=min(min2,x-y);
    }
    cout<<max((max1-min1),(max2-min2));
    return 0;
}

要理解一下这个转化

 


 

接下来 介绍一下切比雪夫距离 

在二维空间内,两个点之间的切比雪夫距离为它们横坐标之差的绝对值与纵坐标之差的绝对值的最大值。

设点 java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_19

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_20

java 计算欧式距离公式 欧式距离算法简单解释_git_21

切比雪夫距离 的一般模型:

在国际象棋棋盘上,国王与王后从一个格子走到另一个格子的最短距离都是切比雪夫距离。

若网格图上的一个点只能到周围 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_22

 


 

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_23

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_24二维曼哈顿距离与切比雪夫距离的相互转化

我这里简单证明一下吧

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_25

或者我还看过一个比较优秀的证明 

假设 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_26java 计算欧式距离公式 欧式距离算法简单解释_git_27

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_28

我们很容易发现,这就是 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_29

所以将每一个点 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_30

同理 java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_31

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_32

 

而这就是 $\displaystyle \left( \frac{x_1+y_1}{2},\frac{x_1-y_1}{2} \right),\left( \frac{x_2+y_2}{2},\frac{x_2-y_2}{2} \right)$ java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_33

所以将每一个点 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_34$\displaystyle \left( \frac{x+y}{2},\frac{x-y}{2}\right)$ java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_35

也就是 两个东西 可以相互转化 那么 对于有些题目 我们就要注意到 怎么计算简单了 

在观察 上面那个问题 求曼哈顿距离 最大的点对 我们考虑转化成切比雪夫距离 那么 就是(x,y) 转化成 (x+y,x-y)

所求的答案就变为 max{max{∣xi−xj∣,∣yi−yj∣}}

在所有点中,横坐标之差的最大值和纵坐标之差的最大值都有可能成为答案,

所以我们只需要预处理出 java 计算欧式距离公式 欧式距离算法简单解释_java 计算欧式距离公式_36

 


 

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_37

java 计算欧式距离公式 欧式距离算法简单解释_git_38

java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_39

我们发现 直接切比雪夫 计算是比较麻烦的 因为处理max 都是至少n^2 的

所以 我们考虑 转化为曼哈顿距离 将每一个点 java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_40

考虑 这个时候 我们进行的就是若干求和 考虑都是绝对值 那么存在大小关系 

所以 我们不妨考虑 排序!

枚举所选的点 java 计算欧式距离公式 欧式距离算法简单解释_git_41

如果某个点 java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_42

这样就可以分两种情况讨论了。

设前 java 计算欧式距离公式 欧式距离算法简单解释_切比雪夫距离_43

 

 

java 计算欧式距离公式 欧式距离算法简单解释_曼哈顿距离_44

 

 

#include<bits/stdc++.h>
using namespace std;
#define N 100100 
typedef long long ll;
ll n,a,b,p[N],x[N],y[N],q[N],prex[N],prey[N],ans=0x7fffffffffffffff;
template<typename T>inline void read(T &x)
{
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x*=f;
}
int main() {
    read(n);
    for(int i=1;i<=n;i++) {
        read(a); read(b);
        x[i]=p[i]=a+b; y[i]=q[i]=a-b;
    }
    sort(p+1,p+n+1); sort(q+1,q+n+1);
    for(int i=1;i<=n;i++) {
        prex[i]=prex[i-1]+p[i]; prey[i]=prey[i-1]+q[i];
    }
    for(int i=1;i<=n;i++) {
        int posx=lower_bound(p+1,p+n+1,x[i])-p;
        int posy=lower_bound(q+1,q+n+1,y[i])-q;
        ll sumx=0,sumy=0;
        sumx=(ll)posx*x[i]-prex[posx]+prex[n]-prex[posx]-(ll)(n-posx)*x[i];
        sumy=(ll)posy*y[i]-prey[posy]+prey[n]-prey[posy]-(ll)(n-posy)*y[i];
        ans=min(ans,sumx+sumy);
    }
    cout<<(ans/2)<<endl;
    return 0;
}

 

当然 这里我也有一个 手写二分的代码 有同学抬杠stl慢

Q次询问 每次给出一个 点(s,t) 求 所有点到它的切比雪夫距离

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &x) {
    x=0;T f=1,ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x*=f;
}
const int N=1010000;
ll T,n,w,s,t,a,b,X[N],Y[N],p[N],q[N],prex[N],prey[N]; 
inline int find(int x)
{
    if(p[n]<=x)return n;
    if(p[1]>=x)return 0;
    int l=1,r=n;
    while(l+1<r)
    {
        int mid=(l+r)>>1;
        if(p[mid]>=x)r=mid;
        else l=mid;
    }
    if(p[r]<=x)return r;
    return l;
}
inline int calc(int x)
{
    if(q[n]<=x)return n;
    if(q[1]>=x)return 0;
    int l=1,r=n;
    while(l+1<r)
    {
        int mid=(l+r)>>1;
        if(q[mid]>=x)r=mid;
        else l=mid;
    }
    if(q[r]<=x)return r;
    return l;
}
int main() {
    read(T);
    while(T--) {
        read(n); read(w);
        for(int i=1;i<=n;i++) {
            read(a); read(b);
            X[i]=p[i]=a+b,Y[i]=q[i]=a-b;
        }
        sort(p+1,p+n+1); sort(q+1,q+n+1);
        for(int i=1;i<=n;i++) {
            prex[i]=prex[i-1]+p[i]; prey[i]=prey[i-1]+q[i];
        }
        for(int i=1;i<=w;i++) {
            read(s); read(t);
            ll xx=s+t,yy=s-t;
            int posx=find(xx);
            int posy=calc(yy);
            ll sumx=0,sumy=0;
            //cout<<posx<<' '<<posy<<endl;
            sumx=(ll)posx*xx-prex[posx]+prex[n]-prex[posx]-(ll)(n-posx)*xx;
            sumy=(ll)posy*yy-prey[posy]+prey[n]-prey[posy]-(ll)(n-posy)*yy;
            printf("%lld\n",(sumx+sumy)/2);
        }
    }
    return 0;
}