題目鏈接: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的區間改爲,則不能開數組進行標記。需要進行離散化處理
把每一個端點拿出來單獨做處理。我們需要記錄位置,還需要區分是左端點還是右端點。
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;
}