朴素做法
刚开始将数组初始化为1,然后进行m个区间的删除操作,即把m个区间标记为0,最后把还剩的所有的1全部相加就是最后剩的个数。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int st[N];
int main()
{
int l,m;cin>>l>>m;
//题目描述是从0~L,一共L+1棵树
for(int i=0;i<=l;i++)st[i]=1;
while(m--)
{
int a,b;cin>>a>>b;
//删除区间
for(int i=a;i<=b;i++)
{
st[i]=0;
}
}
//看一下还剩多少个数
int res=0;
for(int i=0;i<=l;i++)
{
res+=st[i];
}
cout<<res<<endl;
return 0;
}
时间复杂度:一共m个区间,每个区间最大长度是L,一共是O(lm),lm最大1e6。
优化做法: 合并区间算法
我们把所有要删除的区间进行合并,并把每个区间长度相加,最后用总长度L减去合并之后的区间的长度,就是还剩下的数的个数:
#include<bits/stdc++.h>
using namespace std;
#define l first
#define r second
typedef pair<int,int>PII;
const int N=110;
PII v[N];
int main()
{
int len,m;cin>>len>>m;
//输入m个区间
for(int i=0;i<m;i++)
{
cin>>v[i].l>>v[i].r;
}
sort(v,v+m); //PII默认按照左端点排序
//开始合并
int sum=0;
int L=v[0].l,R=v[0].r;
for(int i=1;i<m;i++)
{
if(v[i].l<=R)R=max(R,v[i].r); //如果当前区间的左端点小于前一段区间的右端点,就合并
else //不相交,每一段区间都是独立的
{
sum+=R-L+1; //加上前一段区间的区间和
L=v[i].l,R=v[i].r; //更新前一段区间为当前区间
}
}
sum+=R-L+1; //加上最后一段区间
cout<<len+1-sum<<endl; //还剩多少区间=总区间-合并之后的区间
return 0;
}