Z2093. 城市距离(2025年版)
Description
J国有N个城市,每个城市有其坐标设为(xi,yi)
规定两个城市之间的距离为min(|xi−xj|,|yi−yj|)
现在问J国中距离最远的两个城市之间的距离是?
Format
Input
第一行包含两个整数n
接下n行,每行两个数字代表城市的坐标,其值在[0,1e9]
2<=N<=2e5
Output
如题
Samples
输入数据 1
3
0 3
3 1
4 10
输出数据 1
4
SOl:
Sol
一个非常好的题
首先明确一下,这个题暴力来做是过不了的。于是我们二分一个答案mid,把一个求解问题,转成一个验证性的问题。
只要找对某一对点(x,y),满足
条件1:|xj-xi|>=k
条件2:|yj-yi|>=k
那就Ok了。
接下来考虑如何去掉绝对值。
我们可以按所有点按横坐标进行升序排列
这样当头指针指向i,尾指针指向j
并且满足a[j]-a[i]>=k时,则j及其后面的所有点都会满足条件1
接下来考虑满足条件2。
因为经过前面的处理,j及其后面的所有点都会满足条件1
于是我们只要预处理出
maxx[j],其代表第J个点到第N个点,这些点纵坐标的最大值。
minn[j],其代表第J个点到第N个点,这些点纵坐标的最小值。
于是只要找出来的点满足条件
if(maxx[j]-a[i].y>=k||a[i].y-minn[j]>=k)
于是这个二分出来的答案就是可行的了。


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int maxx[N],minn[N];
struct node
{
int x,y;
}a[N];
bool cmpx(node a,node b)
{
return a.x<b.x;
}
int n;
bool check(int mid)
{
int j=1;
bool ok;
// cout<<"mid is "<<mid<<endl;
for(int i=1;i<=n;i++)
{
while(j<=n&&a[j].x-a[i].x<mid)
j++;
// cout<<"i is "<<i<<endl;
// cout<<"j is "<<j<<endl;
// cout<<maxx[j]<<" "<<minn[j]<<" "<<a[i].y<<endl;
if(maxx[j]-a[i].y>=mid||a[i].y-minn[j]>=mid)
{
// cout<<"find it "<<endl;
return true;
}
}
// cout<<"Not find it "<<endl;
return false;
}
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmpx);
int l=0,r=a[n].x-a[1].x;
maxx[n+1]=-1e9,minn[n+1]=1e9;
for(int i=n;i>=1;i--)
{
maxx[i]=max(maxx[i+1],a[i].y);
minn[i]=min(minn[i+1],a[i].y);
}
int ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
l=mid+1,ans=max(ans,mid);
else
r=mid-1;
}
cout<<ans<<endl;
}
下面这个做法,没有上面那个好理解。
其以J为左点,i为右点
先找到a[i].x-a[j].x>=k的i点
然后不断移动J点,直到不满足条件点的出现
此时对于J点来说,它是一个区间的点,然后统计这个区间的所有点y值的最大值及最小值,再来检测。
需要注意的是maxx,minn是维护的全局的最大值,最小值。

#include <bits/stdc++.h> using namespace std; const int N = 200010; typedef pair<int , int >PII ; int n ; struct node { int x , y ; }all[N] ; bool cmp(node a ,node b ) { return a.x<b.x; } bool check(int k ) { int maxx = -1e9 , minn = 1e9 ;
//必须写在最后面,不能写在下面while循环中 int i=0; int j = 1; while(i<n) { i++; while(j <i && all[i].x - k >= all[j].x) { maxx = max(maxx , all[j].y) ; minn = min(minn , all[j].y) ; j ++ ; } //只有all[i].x - k >= all[j].x 的时候才会更新maxx 和minn if(maxx - all[i].y>= k || all[i].y - minn >= k ) return true; } return false ; } int main() { cin>>n; for(int i = 1 ; i<=n ; i ++ ) cin>>all[i].x>>all[i].y; sort(all+1 ,all + n+1 ,cmp ) ; //按x轴升序排列 int l = 0 , r = 1e9 ; int ans=0; while(l <=r ) { int mid = (l + r )/2 ; if(check(mid)) l = mid+1 ,ans=max(ans,mid); else r = mid - 1 ; } cout<<ans<<endl ; return 0 ; }
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
typedef pair<int , int >PII ;
int n ;
struct node
{
int x , y ;
}all[N] ;
bool cmp(node a ,node b )
{
return a.x<b.x;
}
bool check(int k )
{
int maxx = -1e9 , minn = 1e9 ;
int j = 1;
for(int i = 1 ; i <= n ; i ++ )
{
while(j <i && all[i].x - k >= all[j].x)
{
maxx = max(maxx , all[j].y) ;
minn = min(minn , all[j].y) ;
j ++ ;
}
//只有all[i].x - k >= all[j].x 的时候才会更新maxx 和minn
if(maxx - all[i].y>= k || all[i].y - minn >= k ) return true;
}
return false ;
}
int main()
{
cin>>n;
for(int i = 1 ; i<=n ; i ++ )
cin>>all[i].x>>all[i].y;
sort(all+1 ,all + n+1 ,cmp ) ;
//按x轴升序排列
int l = 0 , r = 1e9 ;
int ans=0;
while(l <=r )
{
int mid = (l + r )/2 ;
if(check(mid))
l = mid+1 ,ans=max(ans,mid);
else
r = mid - 1 ;
}
cout<<ans<<endl ;
return 0 ;
}

浙公网安备 33010602011771号