从暴力到差分/前缀和到离散化
暴力
这题因为数据规划只有1e5 和 100, 所以直接暴力遍历就可以解决.
//暴力方法
using namespace std;
#include<bits/stdc++.h>
int tree[10005];
int main(){
int l,m;
cin>>l>>m;
int left,right;
for(int i=0;i<=l;i++) tree[i]=1;
for(int i=0;i<m;i++)
{
cin>>left>>right;
for(int j=left;j<=right;j++) tree[j]--;
}
int sum=0;
for(int i=0;i<=l;i++)
{
if(tree[i] == 1) sum++;
}
cout<<sum;
return 0;
}
//差分方法
using namespace std;
#include<bits/stdc++.h>
const int maxn=1e5+5;
int a[maxn];
int main(){
int l,m;
cin>>l>>m;
a[0]=1;
for(int i=0;i<m;i++)
{
int x,y;
cin>>x>>y;
a[x]++;
a[y+1]--;
}
int sum=0,tmp=0;
for(int i=0;i<=l;i++)
{
tmp+=a[i];
if(tmp == 1) sum++;
}
cout<<sum;
return 0;
}
差分/前缀和
在这道题中,由于数据规模已经达到了1e8 和 1e6的级别,所以通过暴力的方式来做,复杂度会达到1e14的级别,必然会超时.但1e8的级别的int型数组依旧可以开,所以可以通过差分的方式来解决.
另外注意M已经达到1e6的级别了,如此大量的输入输出,如果直接用cin cout的话无疑会导致超时,所以这里需要用scanf printf.
关于遇到1则sum+1,可以参考下图解释.
using namespace std;
#include<bits/stdc++.h>
const int maxn=1e8+5;
int a[maxn];
int main(){
int l,m;
scanf("%d %d",&l,&m);
int x,y;
a[0]=1;//1'起始值为1,作为是否移走的标记
for(int i=0;i<m;i++)
{
scanf("%d %d",&x,&y);
a[x]++;
a[y+1]--;//2'一定要是y+1,因为y这个点也被移走了
}
int sum=0,tmp=0;
for(int i=0;i<=l;i++)//3'注意从0开始,以及<=l,l这个点也是包括在内的
{
tmp+=a[i];
if(tmp == 1) sum++;
}
printf("%d",sum);
return 0;
}
离散化
离散化是由于L的规模已经太大了,数组开不下去了才采用的.
//校门外的树
using namespace std;
#include<bits/stdc++.h>
const int maxn=1e5+5;
struct node{
int pos,num;
}a[maxn];
bool cmp(node x,node y){
return x.pos<y.pos;
}
int main(){
int l,m;
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,cnt=0;
for(int i=1;i<=2*m;i++)
{
sum+=a[i].num;
if(sum == 1 && a[i].num == 1)//从0变1的时候
{
cnt+=a[i].pos-a[i-1].pos;
}
}
cnt+=l-a[2*m].pos+1;
cout<<cnt;
return 0;
}