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,显然不是正确解。