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
思路:
一眼就知道是贪心,要对开始和结束进行排序,开始坑定是升序的排序,降序直接就降序排序,之前交了两遍,两个for不管怎么优化,第16组wa了(不懂为什么),最后四组超限。反正我也只是用(n^2)的算法去测试一下测试数据~
反思:用两个for一个存放被比较的线段,一个存放当前线段,这样写会超时,现在想一下可不可以优化一下。其实正真需要的是被比较线段的结尾,开头并不需要,因为经过排序,所有的开头都在这个开头的后面。结尾呢,真正需要的是一个比较远的位置(在这个部分,开始的排序就比较重要了,因为所有的起点都是按升序排序的,下一段的起点不可能包含上一段的起点!!![这个部分非常重要])到这里就可以把一个for循环优化成一个标记数字了,前i-1个点当中结束为主最远的点。
代码讲解:
#include<iostream>
#include<algorithm>
using namespace std;
struct segment{
int s, e;
}se[50100];
bool cmp(segment a, segment b){
if(a.s != b.s) return a.s < b.s;
else return a.e > b.e;
}
int main(){
int t;
cin >> t;
for(int i = 0; i < t; i++)
cin >> se[i].s >> se[i].e;
sort(se,se+t,cmp);
int e = se[0].e, maxn = 0;//e为那个标记,前i-1个线段最远的结束位置
for(int i = 1; i < t; i++){
if(se[i].e > e) maxn = max(maxn , e - se[i].s) , e = se[i].e;//先找到重叠的线段,再更新下标
else maxn = max(maxn , se[i].e - se[i].s);
}
cout << maxn << endl;
return 0;
}