NOIP2005
校门外的树
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客
题目描述
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入描述:
第一行有两个整数:L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出描述:
包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
解法一:前缀和:
思路:将区间L,R减去一,在R+1的位置上+1,然后求出前缀和,还原数组,然后遍历数组,寻找数值为0的,将他们加起来即是答案。
#include<iostream>
#include<string.h>
using namespace std;const int maxn = 1e5;
int num[maxn];
int main(){int l,m;cin>>l>>m;memset(num,0,sizeof(num));while(m--){//差分int L,R;cin>>L>>R;num[L]-=1;num[R+1]+=1;}int cnt=0;for(int i =1;i<=l;i++)num[i]=num[i-1]+num[i];//利用前缀和还原数组for(int i=0;i<=l;i++){if(num[i]==0){//为0即为没有移除的树cnt++;}}cout<<cnt<<endl;}
解法二 :合并区间
思路:先将区间的做区间排序,然后进行合并,然后遍历区间,将每一个区间的差值相加,然后用总数减去他要移除的
#include<iostream>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn =1e5;
struct node
{long long l,r;}s[maxn];
bool cmp(node a,node b){if(a.l==b.l){return a.r<b.r;}return a.l<b.l;
}
int main(){long long num,m;cin>>num>>m;for(int i =0;i<m;i++){cin>>s[i].l>>s[i].r;}sort(s,s+m,cmp);long long ll=s[0].l,rr =s[0].r,ans=0;for(int i =1;i<m;i++ ){if(s[i].l<=rr){rr=max(s[i].r,rr);}else{ans+=(rr - ll+1);ll=s[i].l;rr = s[i].r;}}ans+=(rr-ll+1);cout<<num-ans<<endl;
}