牛客算法競賽入門課第一節習題 校門外的樹(差分思想&數據擴大:離散處理)

題目鏈接:https://ac.nowcoder.com/acm/problem/16649

題目描述
某校大門外長度爲L的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1米。我們可以把馬路看成一個數軸,馬路的一端在數軸0的位置,另一端在L的位置;數軸上的每個整數點,即0,1,2,……,L,都種有一棵樹。
由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起始點和終止點的座標都是整數,區域之間可能有重合的部分。現在要把這些區域中的樹(包括區域端點處的兩棵樹)移走。你的任務是計算將這些樹都移走後,馬路上還有多少棵樹。
輸入描述:
第一行有兩個整數:L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表馬路的長度,M代表區域的數目,L和M之間用一個空格隔開。接下來的M行每行包含兩個不同的整數,用一個空格隔開,表示一個區域的起始點和終止點的座標。
輸出描述:
包括一行,這一行只包含一個整數,表示馬路上剩餘的樹的數目。

輸入

500 3
150 300
100 200
470 471

輸出

298

分析:

區間最大爲10000,可以開數組。對於每一個區間需要把這個區間的所有樹移走,可以看成對於每一個區間內的所有數加1,本來0~L所有的,最後的結果是區間內的數沒有加過的數的個數。
這是典型的差分模型:
在這裏插入圖片描述

代碼:

#include<iostream>
#include<cstdio>
#include<math.h>
#include<stdlib.h>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e4+10;
struct node
{
    int l,r;

} a[N];
int L,M;
int b[N];
int main()
{
    cin>>L>>M;
    for(int i=1; i<=M; i++)
    {
        cin>>a[i].l>>a[i].r;
        if(a[i].l>a[i].r)
            swap(a[i].l,a[i].r);
    }
    for(int i=1; i<=M; i++)
    {
        b[a[i].l]++;///對於每個區間改變的只是區間兩個端點與前一個數的差值
        b[a[i].r+1]--;
    }
    int res=0;
    if(b[0]==0)
        res++;///特判0的位置
    for(int i=1; i<=L; i++)
    {
        b[i]+=b[i-1];///前綴和得到每一個位置的值
        if(b[i]==0)///這個值沒有加過,對應的結果加1        
           res++;
    }
    cout<<res<<endl;
    return 0;
}

若L的區間改爲1<=L<=1091<=L<=10^9,則不能開數組進行標記。需要進行離散化處理

把每一個端點拿出來單獨做處理。我們需要記錄位置,還需要區分是左端點還是右端點

 for(int i=1; i<=M; i++)
    {
        int x,y;
        cin>>x>>y;
        a[2*i-1].pos=x;
        a[2*i-1].num=1;///左端點用1來記錄
        a[2*i].pos=y+1;///右端點+1的位置用-1記錄
        a[2*i].num=-1;
    }

把pos從小到大排序:

sum記錄num的前綴和,當sum從0到1的時候,對應有一段沒有覆蓋的區間,結果爲區間的長度。

    int sum=0;
    int ans=0;
    for(int i=1; i<=2*M; i++)
    {
        sum+=a[i].num;
        if(sum==1&&a[i].num==1)///0--->1
            ans+=a[i].pos-a[i-1].pos;
    }

最後還需要加上L到最後一個點的距離

ans+=L-a[2*M].pos+1;

樣例:
在這裏插入圖片描述
完整代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2*1e2+10;
struct node
{
    int pos;
    int num;
} a[N];
int L,M;
bool cmp(node u,node v)
{
    return u.pos<v.pos;
}
int main()
{
    cin>>L>>M;
    for(int i=1; i<=M; i++)
    {
        int x,y;
        cin>>x>>y;
        a[2*i-1].pos=x;
        a[2*i-1].num=1;
        a[2*i].pos=y+1;
        a[2*i].num=-1;
    }
    sort(a+1,a+2*M+1,cmp);
    int sum=0;
    int ans=0;
    for(int i=1; i<=2*M; i++)
    {
        sum+=a[i].num;
        if(sum==1&&a[i].num==1)///有0--->1
            ans+=a[i].pos-a[i-1].pos;
    }
    ans+=L-a[2*M].pos+1;
    cout<<ans<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章