AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

AcWing 422. 校门外的树    原题链接    简单

作者: 作者的头像   yxc ,  2019-07-25 20:39:31 ,  所有人可见 ,  阅读 3897


21


15

算法1

(模拟,数组遍历) $O(ML)$

定义一个长度为 $L + 1$ 的布尔数组,表示每棵树的状态。

  • true 表示已经被移走;
  • false 表示未被移走;

对于每次移动树木的操作 $[L_i, R_i]$,直接循环一遍,将布尔数组中从 $L_i$,到 $R_i$ 这段赋值为true。

最后统计值为 false 的数量即可。

时间复杂度分析

对于每次移动树木的操作,最坏情况下区间长度是 $O(L)$,因此计算量是 $O(L)$,一共有 $M$ 次操作,因此总时间复杂度是 $O(ML) = 100 \times 10000 = 10^6$。

C++ 代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010;

int n, m;
bool st[N];

int main()
{
    scanf("%d%d", &m, &n);
    while (n -- )
    {
        int l, r;
        scanf("%d%d", &l, &r);
        for (int i = l; i <= r; i ++ ) st[i] = true;
    }

    int res = 0;
    for (int i = 0; i <= m; i ++ )
        if (!st[i])
            res ++ ;

    printf("%d\n", res);

    return 0;
}

算法2

(区间合并) $O(MlogM)$

先求出所有移动树木的操作的区间的并集,那么马路上剩余部分即为最终剩下树木的部分。

求所有区间的并集可以使用区间合并算法,可以参考 AcWing 803. 区间合并。

时间复杂度分析

区间合并算法的时间复杂度是 $O(MlogM)$,其中 $M$ 是区间数量。

C++ 代码

#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

const int N = 110;

int n, m;
PII seg[N];

int main()
{
    cin >> m >> n;

    for (int i = 0; i < n; i ++ ) cin >> seg[i].first >> seg[i].second;

    sort(seg, seg + n);

    int res = m + 1;
    int st = seg[0].first, ed = seg[0].second;
    for (int i = 1; i < n; i ++ )
        if (seg[i].first <= ed) ed = max(seg[i].second, ed);
        else
        {
            res -= ed - st + 1;
            st = seg[i].first, ed = seg[i].second;
        }

    res -= ed - st + 1;

    cout << res << endl;

    return 0;
}

12 评论


用户头像
ywb   2021-01-16 10:02      4    踩      回复

算法四:差分思想

int main() {
    cin >> n >> m;
    int l, r;
    while (m --) {
        cin >> l >> r;
        f[l] --;
        f[r + 1] ++;
    }

    int val = 1, res = 0;
    for (int i = 0; i <= n; i ++) {
        val += f[i];
        res += (val >= 1);
    }
    cout << res;
    return 0;
}
用户头像
Andy0229   2021-01-16 15:59         踩      回复

666

用户头像
hongrubb   2021-01-16 21:50         踩      回复

感觉差分好难想。

用户头像
RobsonChen   2021-01-17 16:18         踩      回复

厉害,没反应过来,区间加减用差分做

用户头像
狗蛋儿_   10个月前         踩      回复

给你点个赞~

用户头像
Lena   6个月前      1    踩      回复

我觉得这个解法挺有意思的, 这个树被移掉, 只可能移掉一次, 不可能两次的,所以从差分数组还原成原始数组后,
得到的是一颗树被移掉了几次, 只要大于0, 这棵树就一定在, 如果小于0, 这棵树肯定不在. 所以是res += (val >= 1)


用户头像
whsstory   2019-11-04 16:49      2    踩      回复

算法三:线段树暴力维护区间推平.....

用户头像
yxc   2019-11-04 16:51         踩      回复

很强

用户头像
whsstory   2019-11-04 16:56    回复了 yxc 的评论         踩      回复

%%%

用户头像
寒江   2020-12-27 16:02         踩      回复

大哥不妨写一写


用户头像
huge_luck   2021-01-16 16:52         踩      回复

pair 下标必须从0开始吗,我从1开始 就不对,改成0就对了

用户头像
萝卜嘞   2021-01-18 10:55         踩      回复

0到L都有树


你确定删除吗?

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息