平面几何的几个距离

欧几里得距离:

\(n\) 维空间的表示就是

\[\sqrt{\sum\limits^{n}_ {i=1} (ax_i-ay_i)^2} \]

感觉好装的样子……

曼哈顿距离

\[\sum\limits_{i=1}^{n} |ax_i-ay_i| \]

还是感觉好装的样子

切比雪夫距离

\[\max\limits_{i=1}^{n} |ax_i-ay_i| \]

就是坐标差的绝对值的极值

然后我们思考曼哈顿距离和切比雪夫距离的关系:

请在纸上建一个二维坐标系,然后画一个与原点曼哈顿距离为 \(5\) 的正方形 \(S_1\)

然后再画一个切比雪夫距离为 \(5\) 的正方形 \(S_2\)

看看它们,是不是有某种奇妙的联系:\(S_1\) 旋转 \(45\) 度后放大为原来原来的两倍就是 \(S_2\)

互相转化的公式为$(x,y) \ on\ S_1 \rightarrow(\frac{x+y}{2},\frac{x-y}{2}) \ on\ S_2 $

这里可以用来使某些题的处理更加方便,比如:

Luogu5193 [TJOI2012]炸弹

题意转化:

给一个二维平面和一堆点,如果两个点的曼哈顿距离小于等于定值就连边

最后求图上连通块个数

\(n\le 10^5\)

曼哈顿两个维度有点头疼,不好处理,那我们转切比雪夫

这样我们把距离转成了以每个点为原点,在定边长切比雪夫距离矩形中框点

我们上 \(map\) 扫描线就行了

我们在处理每个点的时候就直接找那个离他 \(y\) 最近的上下两个就行了

因为那个点已经考虑了前面的点

Code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
		return res*f;
	}
	const int N=1e5+10;
	struct node{
		int x,y;
		#define x(i) p[i].x
		#define y(i) p[i].y
	}p[N];
	int ans,n,fa[N],r;
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline bool cmp(node a,node b)
	{
		return a.x<b.x;
	}
	map<int,int> mp;
	signed main()
	{
		n=read(); r=read();
		for(int i=1,tx,ty;i<=n;++i)
		{
			fa[i]=i; tx=read(),ty=read();
			x(i)=(tx+ty); y(i)=(tx-ty);
		} 
		mp[1e15+10]=-1;
		mp[-1e15-10]=-1;
		sort(p+1,p+n+1,cmp);
		int now=1;
		for(int i=1;i<=n;++i)
		{
			while(now<n&&x(now)+r<x(i)) 
			{
				if(mp[y(now)]==now) mp.erase(y(now));
				++now;
			}
			map<int,int>::iterator it=mp.lower_bound(y(i));
			if(y(i)+r>=(*it).first) 
			{
				
				int t=(*it).second; 
				if(find(t)!=find(i)) 
				{
					fa[find(t)]=find(i),ans--;
				}
			}
			it--; 
			if(y(i)<=(*it).first+r)
			{
				int t=(*it).second; 
				if(find(t)!=find(i)) 
				{
					fa[find(t)]=find(i),ans--;
				}
			}
			mp[y(i)]=i;
		}printf("%lld\n",ans+n);
		return 0;
	}
}
signed main(){return yspm::main();}

猜你喜欢

转载自www.cnblogs.com/yspm/p/12784289.html