校门外的树
某校大门外长度为 L L L的马路上有一排树,每两棵相邻的树之间的间隔都是 1 1 1米。
我们可以把马路看成一个数轴,马路的一端在数轴 0 0 0的位置,另一端在 L L L的位置;数轴上的每个整数点,即 0 , 1 , 2 , … … , L , 0,1,2,……,L, 0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。
这些区域用它们在数轴上的起始点和终止点表示。
已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。
现在要把这些区域中的树(包括区域端点处的两棵树)移走。
你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入格式
输入文件的第一行有两个整数
L
L
L和
M
,
L
M,L
M,L代表马路的长度,
M
M
M代表区域的数目,
L
L
L和
M
M
M之间用一个空格隔开。
接下来的 M M M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出格式
输出文件包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
数据范围
1
≤
L
≤
10000
,
1≤L≤10000,
1≤L≤10000,
1
≤
M
≤
100
1≤M≤100
1≤M≤100
输入样例:
500 500 500 3 3 3
150 150 150 300 300 300
100 100 100 200 200 200
470 470 470 471 471 471
输出样例:
298 298 298
分析: 此题一看就是区间合并问题,不过也可以用暴力的做法做
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
bool a[N];
int main(){
int l,m,i,j,sum=0,left,right;
cin>>l>>m;
for(i=0;i<m;i++){
cin>>left>>right;
for(j=left;j<=right;j++){
a[j]=1;
}
}
for(i=0;i<=l;i++){
if(a[i]==0){
sum++;
}
}
cout<<sum<<endl;
}
也可以用差分优化一下:
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
bool a[N];
int b[N];
int main(){
int l,m,i,j,sum=0,left,right;
cin>>l>>m;
for(i=0;i<m;i++){
cin>>left>>right;
b[left]++;
b[right+1]--;
}
for(i=0;i<=l;i++){
b[i]+=b[i-1];
if(b[i]==0){
sum++;
}
}
cout<<sum<<endl;
}
优化算法:区间合并,我以前发过文章:区间合并
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node{
int l,r;
}a[N],b[N];
bool cmp(node a,node b){
return a.l<b.l;
}
int main(){
int l,m,i;
cin>>l>>m;
for(i=0;i<m;i++){
cin>>a[i].l>>a[i].r;
}
sort(a,a+m,cmp);
int right=a[0].r,left=a[0].l,ans=1,sum=0;
b[ans].l=left,b[ans].r=right;
for(i=1;i<m;i++){
if(a[i].l>right){
b[ans].l=left;
b[ans].r=right;
ans++;
left=a[i].l;
right=a[i].r;
}
else{
right=max(right,a[i].r);
b[ans].r=right;
}
}
b[ans].l=left;
b[ans].r=right;
for(i=1;i<=ans;i++){
sum+=b[i].r-b[i].l+1;
}
cout<<l-sum+1<<endl;
}