https://ac.nowcoder.com/acm/contest/20960/1009
对数据范围较小的情况,直接暴力枚举即可。
或者利用差分的思想,先做差分,再做前缀和。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int maxn = 1e4+3;
int det[maxn],prefix[maxn];
void solve()
{
int l,n;
cin>>l>>n;
int x,y;
while(n--)
{
cin>>x>>y;
det[x]++;
det[y+1]--;
}
int cnt=0,sum=0;
for(int i=0;i<=l;i++)
{
sum+=det[i];
if(sum==0) cnt++;
}
cout<<cnt<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--) solve();
return 0;
}
https://ac.nowcoder.com/acm/contest/20960/1010
数据范围增大后,暴力行不通,这里有两种方法。
法1:记录下每个区间的左右端点,将区间按照左端点从小到大排序,枚举一遍区间,求出被拔走的树的数量,再用总的减去被拔走的即可。
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int maxn = 1e5+3;
struct Loc
{
int x,y;
};
Loc a[maxn];
bool cmp(Loc x,Loc y)
{
if(x.x==y.x) return x.y<y.y;
else return x.x<y.x;
}
void solve()
{
int l,n;
cin>>l>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x>>a[i].y;
}
sort(a+1,a+1+n,cmp);
int tempx=a[1].x;
int tempy=a[1].y;
int cnt=0;
for(int i=2;i<=n;i++)
{
if(a[i].x>=tempx&&a[i].x<=tempy)
{
tempy=max(tempy,a[i].y);
}
else
{
cnt+=tempy-tempx+1;
tempx=a[i].x;
tempy=a[i].y;
}
}
cnt+=tempy-tempx+1;
cout<<l+1-cnt<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--) solve();
return 0;
}
法二:离散化,再利用差分的思想。
// 离散化解法
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>
using namespace std;
const int maxn = 2e5+3;
struct Loc
{
int loc,num;
};
Loc a[maxn];
bool cmp(Loc x,Loc y)
{
if(x.loc==y.loc) return x.num>y.num;
else return x.loc<y.loc;
}
void solve()
{
int l,n;
cin>>l>>n;
int x,y;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
a[i].loc=x;
a[i].num=1;
a[i+n].loc=y;
a[i+n].num=-1;
}
int sum=0;
int ans=0;
sort(a+1,a+1+2*n,cmp);
ans+=a[1].loc;
sum+=a[1].num;
for(int i=2;i<=2*n;i++)
{
sum=sum+a[i].num;
if(sum==1&&a[i].num==1)
ans+=a[i].loc-a[i-1].loc-1;
}
ans+=l-a[2*n].loc;
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T=1;
while(T--) solve();
return 0;
}