基准时间限制:1 秒 空间限制:131072 KB 分值: 5
难度:1级算法题
X轴上有N条线段,每条线段包括1个起点和终点。线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]。
给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长的。输出这个最长的距离。如果没有重叠,输出0。
Input
第1行:线段的数量N(2 <= N <= 50000)。 第2 - N + 1行:每行2个数,线段的起点和终点。(0 <= s , e <= 10^9)
Output
输出最长重复区间的长度。
Input示例
5 1 5 2 4 2 8 3 7 7 9
Output示例
4
题意:给出n个区间,找出其中两个区间重合的最大长度。
解析:贪心。这题的n有点大,所以n*n的复杂度行不通。排序是必不可少的。那么问题就来了,怎么排序?要把所有的区间全部考虑到(保证有交集的区间都要算到),那么就先把左边界升序排,如果左边界相同就按右边界降序。至于这里为什么按右边界降序排序,保证占到的交集最大,举个例子,【1,6】【2,4】【2,8】,显然【2,8】与【1,6】的交集最大。排好序后,再来看如何处理这些区间。双重循环(全枚举)用不了,那么就保护右端点,一边判断一边求最大值。重合的线段长一定是两区间的右端点最小值减去后一位元素的左端点。每次取到的左端点也要考虑,举个例子【1,6】【1,2】【3,5】这里,不能做完【1,6】和【1,2】后就直接把左端点移到2,这样明明是【3,5】与【1,6】有交集,处理一下就没有交集了,所以每次做完要维护左端点,取两区间的做大左端点。以下是我的代码
#include <stdio.h>
#include <stdlib.h>
int max(int m,int n)
{
return m>n?m:n;
}
int min(int m,int n)
{
return m>n?n:m;
}
typedef struct time
{
int s;
int e;
} T;
T arr[50005];
int cmp(const void*a,const void*b)
{
T *A=(T *)a;
T *B=(T *)b;
if(A->s!=B->s) return A->s-B->s;
else return B->e-A->e;
}
int main()
{
int n;
//freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d%d",&arr[i].s,&arr[i].e);
qsort(arr,n,sizeof(T),cmp);
int maxn=0;
int end=arr[0].e;
for(int i=1; i<n; i++)
{
maxn=max(maxn,min(arr[i].e,end)-arr[i].s);
end=max(arr[i].e,end); //主要就是这一步,保留正确的左端点
}
printf("%d\n",maxn);
return 0;
}