校门外的树

简介: 校门外的树


题目描述

学校大门外长度为的马路上有一排树,每两棵相邻的树之间的间隔都是1米。可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在的位置,数轴上的每个整数点(即0,1,2,……,)都有一棵树。

由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任意区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。请计算将这些树都移走后,马路上还有多少棵树。

输入

样例输入

500 3

150 300

100 200

470 471

样例输出

298

做法1 —— 模拟

#include <bits/stdc++.h>
using namespace std;
int main() {
    int L, M;
    cin >> L >> M;
    vector<int> trees(L + 1, 1);
    while (M--) {
        int l, r;
        cin >> l >> r;
        fill(trees.begin() + l, trees.begin() + r + 1, 0);
    }
    cout << accumulate(trees.begin(), trees.end(), 0);
    return 0;

做法2 —— 排序

#include <bits/stdc++.h>
using namespace std;
struct Segment {
    /* 线段的左端点和右端点 */
    int left, right;
    Segment(int left, int right) : left(left), right(right) {}
    /* 对优先队列的“小于号”进行重载 */
    bool operator<(const Segment &other) const {
        /* C++中的优先队列默认实现为最大堆 此处我们需要使用“大于号”以实现最小堆 */
        return left > other.left || (left == other.left && right > other.right);
    }
    bool operator==(const Segment &other) const {
        return left == other.left && right == other.right;
    }
    /* 对线段进行合并 如成功合并返回true 否则返回false */
    bool merge(const Segment &other) {
        /* 不相交 - 线段1的右端点 在 线段2的左端点 的左侧 */
        if (right < other.left) return false;
        /* 相交 - 合并后的线段存放在线段1中 左端点不变 右端点取两者中较大值 */
        right = max(right, other.right);
        return true;
    }
};
int main() {
    int L, M;
    cin >> L >> M;
    priority_queue<Segment> pq;
    for (int i = 0, left, right; i < M; ++i) {
        cin >> left >> right;
        pq.emplace(Segment(left, right));
    }
    int cnt = 0;
    while (pq.size() >= 2) {
        Segment s1 = pq.top();
        pq.pop();
        Segment s2 = pq.top();
        pq.pop();
        if (s1.merge(s2)) {
            pq.push(s1);
        } else {
            /* 两条线段不相交 因此线段1不会与任何线段相交 统计线段1中被砍伐的树木数量 */
            cnt += s1.right - s1.left + 1;
            /* 线段2并未参与合并过程 将其退回堆中等待下次操作 */
            pq.push(s2);
        }
    }
    /* 堆中最后还剩下一条未处理的线段 */
    if (!pq.empty()) cnt += pq.top().right - pq.top().left + 1;
    cout << L + 1 - cnt << endl;
    return 0;
}
相关文章
|
算法 Android开发 C++
LeetCode 周赛上分之旅 #49 再探内向基环树
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
91 1
|
6月前
校门外的树
校门外的树
22 0
|
测试技术 C++
【C++从0到王者】第三十三站:AVL树
【C++从0到王者】第三十三站:AVL树
35 0
|
C++
【C++从0到王者】第二十七站:搜索二叉树
【C++从0到王者】第二十七站:搜索二叉树
45 0
校门外的树(三种解法,非直接暴力)
校门外的树(三种解法,非直接暴力)
|
算法
回溯算法——我欲修仙(功法篇)
回溯算法——我欲修仙(功法篇)
106 0
[软考]之树和二叉树
[软考]之树和二叉树
81 0
|
算法 程序员
【算法集训专题攻克篇】第二十篇之二叉搜索树
【算法集训专题攻克篇】第二十篇之二叉搜索树
【算法集训专题攻克篇】第二十篇之二叉搜索树
|
人工智能 vr&ar C++
202104-4校门外的树
202104-4校门外的树
85 0
202104-4校门外的树
下一篇
无影云桌面