基准时间限制: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
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1091
题意:给N段线段,输出重叠线段的最长重叠长度。
解题思路:最开始看完题目还没看数据范围的时候就想着暴力解决(女汉子的思路,哈哈哈),后来看到N有50000,N平方的时间复杂度肯定会超,所以就回归正常路线,后来看到题目给的提示是贪心,就想着把N条线段排个序,按照左区间的升序和右区间的升序排序,记录下之前出现线段的最右区间的值,每次取线段的时候如果当前线段的右区间比记录的右区间大的话,那么这条线段和之前出现线段的重合长度记录的最长右区间减去的当前线段的左区间。然后把最右区间的的值更新,如果当前线段的右区间比记录的最右区间小的话那么当前线段与之前线段的重合长度就是当前线段本身。
AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 50000 + 10;
int N;
struct Segment{
int s;
int e;
};//记录线段左右区间的结构体
bool cmp(Segment s1,Segment s2)
{
if(s1.s!=s2.s) return s1.s<s2.s;//按照线段的左区间的升序排序
return s1.e<s2.e;//如果左区间相等就按右区间的升序排序
}
Segment seg[MAXN];
void solve()
{
sort(seg,seg+N,cmp);//排序
int ans;//答案,最长重合长度
int max_r;//记录线段的最右区间值
ans=0;
max_r=seg[0].e;
for(int i=1;i<N;i++)
{
if(seg[i].e>max_r)//当前线段的右区间值比max_r大
{
ans=max(ans,max_r-seg[i].s);//更新ans为max(之前记录的最长重合长度,当前线段与之前线段的重合长度)
max_r=seg[i].e;//更新max_r的值。
}
else ans=max(ans,seg[i].e-seg[i].s);//更新ans为max(之前记录的最长重合长度,当前线段的长度)
}
printf("%d\n",ans);
}
int main(void)
{
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d%d",&seg[i].e,&seg[i].s);
if(seg[i].e<seg[i].s)//避免输入的线段区间左区间比右区间大
{
swap(seg[i].e,seg[i].s);
}
}
solve();
return 0;
}