D - 线段线段(贪心)

X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,10201020和12251225的重叠部分为12201220。

给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。

Input

第1行:线段的数量N(2 <= N <= 50000)。 
第2 - N + 1行:每行2个数,线段的起点和终点。(0 <= s , e <= 10^9) 

Output

输出最长重复区间的长度。

Sample Input

5
1 5
2 4
2 8
3 7
7 9

Sample Output

4

 解题思路:这道题用贪心很好求解,先用sort将起点按从小到大的顺序排列,如果起点相同则按终点从大到小的顺序排列,

因为要找区间的最大长度,所以起点按从小到大的顺序排列,起点相同终点为什么按从大到小的顺序?

显然样例中(1,5)(2,8)区间的重叠长度大于(1,5),(2,4),区间的重叠长度。(贪心算法,从最接近最优解考虑)

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	int x,y;
}a[50000];//定义结构体储存线段, 
bool cmp(node a,node b)//解题思路中的排序规则 
{
	if(a.x==b.x) return a.y>b.y;
	else return a.x<b.x;
}
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i].x>>a[i].y;
	sort(a,a+n,cmp);//排序 
	node b=a[0];//用来记录当前用来计算重叠区间的初线段 
	int max1=0;// 设刚开始重叠长度为0; 
	for(int i=1;i<n;i++)
	{
		if(b.y>a[i].y) max1=max(max1,a[i].y-a[i].x);//如果新的重叠长度比max1大,替换 , 
		else if(a[i].y>=b.y)
		{
			max1=max(max1,b.y-a[i].x);
			b=a[i];// 将a[i]记为下次计算的初线段,if语句中为什么计算重叠长度后没有b=a[i]?看下面的解释 
		 } 
	}
	cout<<max1<<endl;
}

if语句计算重叠长度后之所以没有把a[i]标记为初线段,是因为可能会出现这种情况:b=(1,8),a[1]=(2,4) ,a[2]=(3,7),

显然先判断b与a[1],此时max1=2,但是b与a[2]的重叠长度为4,如果if语句后将b=a[i],那么下次计算的重叠区间为(2,4)和(3,7)的此时最大重叠长度为1,显然不是正确解。

猜你喜欢

转载自blog.csdn.net/qq_40707370/article/details/81363743