51nod 1091 線段重疊(貪心

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;
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章