【题解】校门外的树(前缀和,差分)

题目来源:
校门外的树

  1. 方法一:
    假设每个点的树为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;
}
  1. 方法二:
    利用前缀和计算。初始化全部的树为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++;
    }
posted @ 2020-05-19 16:12  zzzzzy2k  阅读(88)  评论(0编辑  收藏  举报