【题解】校门外的树(前缀和,差分)
题目来源:
校门外的树
- 方法一:
假设每个点的树为1,将区间中的树减一,使其小于1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int check[10001];
int main()
{
int L,M;
cin >> L >> M;
int l[M],r[M];
for(int i = 0;i<=L;i++)
{
check[i] = 1;
}
for(int i = 0;i<M;i++)
{
cin >> l[i] >> r[i];
for(int j = l[i];j<=r[i];j++)
{
check[j]--;
}
}
int ans = 0;
for(int i = 0;i<=L;i++)
{
if(check[i] == 1)
ans++;
}
cout << ans << endl;
return 0;
}
- 方法二:
利用前缀和计算。初始化全部的树为0,标记左端点和右端点,左端点加一,右端点的后一位树减一,再记录全部树的值,如果为0代表没有被移走。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int main()
{
int L,M;
cin >> L >> M;
int tree[10001] = {0},mov[10001]={0};
int a,b;
for(int i = 0;i<M;i++)
{
cin >> a >> b;
mov[a]++;//记录左端点
mov[b+1]--;//记录右端点
}
tree[0] = mov[0];//(0+mov[0])
for(int i = 1;i<=L;i++)
{
tree[i] = tree[i-1]+mov[i]; //算出每项的值
}
int ans = 0;
for(int i = 0;i<=L;i++)
{
if(tree[i]==0)//等于0就是没有被移除
{
ans++;
}
}
cout << ans << endl;
return 0;
}
其中
tree[0] = mov[0];//(0+mov[0])
for(int i = 1;i<=L;i++)
{
tree[i] = tree[i-1]+mov[i]; //算出每项的值
}
int ans = 0;
for(int i = 0;i<=L;i++)
{
if(tree[i]==0)//等于0就是没有被移除
{
ans++;
}
}
可以改进为
int ans = 0,sum = 0;
for(int i = 0;i<=L;i++)
{
sum += mov[i];
if(!sum) ans++;
}