1. 程式人生 > >51nod 1091 線段的重疊【貪心/區間覆蓋類】

51nod 1091 線段的重疊【貪心/區間覆蓋類】

數量 out spa lis black 直接 明顯 ack aps

1091 線段的重疊技術分享 基準時間限制: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

【分析】:(http://www.cnblogs.com/ECJTUACM-873284962/p/6665489.html?utm_source=itdadao&utm_medium=referral)
首先: 先將輸入的區間起點按升序排序,若起點相同則按終點降序排序
比如5組區間:(1 5)(2 4)(2 8)(3 7)(7 9)
按上面所述排序: (1 5) (2 8) (2 4) (3 7) (7 9)
這樣很直觀,為什麽要起點升序,起點相同則按終點降序排序
起點升序很容易理解,我們要找區間覆蓋最大長度
起點相同則按終點降序排序 明顯(1 5)(2 8) 區間覆蓋長度大於 (1 5)(2 4)
1區間覆蓋
2區間包含跟不包含(一起處理)

(應該選定一個參考區間)
1 區間覆蓋: 直接是小區間的距離(2 8)(2 4) 直接是4-2=2;
2 區間包含跟不包含: 區間包含,就是第一個區間終點跟第二個區間起點的差值,eg: (1 5) (2 8) 即5-2=3
假如(1 5)是參考區間,那麽比較完(1 5) (2 8)。參考區間應該為下一個區間,即(2 8).
因為後面的區間起始點都不比(2 8)小(起點升序)。又因為區間包含,就是第一個區間終點跟第二個區間起點的差值。
那麽後面的區間跟(1 5)區間覆蓋長度都沒有比(2 8)區間覆蓋長度大。所以這時再以(1 5)作為參考區間沒有意義了。
為方便起見,就選取下一個區間作為參考區間,即(2 8).
總結一下:
1.先將輸入的區間起點按升序排序,若起點相同則按終點降序排序
2.分兩部分處理:區間覆蓋+區間包含跟不包含

【代碼】:
技術分享
#include <bits/stdc++.h>

using namespace std;
struct node
{
    int l,r;
}a[50000+10];

bool cmp(node a,node b)
{
    if(a.l!=b.l)
        return a.l<b.l;
    else
    {
        if(a.r!=b.r)
            return a.r>b.r;
    }
}
int main()
{
    int n,ans;
    while(cin>>n)
    {
        ans=0;
        for(int i=0;i<n;i++)
            cin>>a[i].l>>a[i].r;
        sort(a,a+n,cmp);
        node m=a[0];
        for(int i=1;i<n;i++)
        {
            if(a[i].r<=m.r)
                ans=max(ans, a[i].r-a[i].l);
            else 
            {
               ans=max(ans, m.r-a[i].l);
               m=a[i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
View Code

51nod 1091 線段的重疊【貪心/區間覆蓋類】