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 ;
}

  

posted @ 2023-05-07 21:51  我微笑不代表我快乐  阅读(8)  评论(0)    收藏  举报