P1047 [NOIP 2005 普及组] 校门外的树——线段覆盖【模板】
题目描述
某校大门外长度为 \(l\) 的马路上有一排树,每两棵相邻的树之间的间隔都是 \(1\) 米。我们可以把马路看成一个数轴,马路的一端在数轴 \(0\) 的位置,另一端在 \(l\) 的位置;数轴上的每个整数点,即 \(0,1,2,\dots,l\),都种有一棵树。
由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入格式
第一行有两个整数,分别表示马路的长度 \(l\) 和区域的数目 \(m\)。
接下来 \(m\) 行,每行两个整数 \(u, v\),表示一个区域的起始点和终止点的坐标。
输出格式
输出一行一个整数,表示将这些树都移走后,马路上剩余的树木数量。
输入输出样例 #1
输入 #1
500 3 150 300 100 200 470 471
输出 #1
298
说明/提示
【数据范围】
- 对于 \(20\%\) 的数据,保证区域之间没有重合的部分。
- 对于 \(100\%\) 的数据,保证 \(1 \leq l \leq 10^4\),\(1 \leq m \leq 100\),\(0 \leq u \leq v \leq l\)。
【题目来源】
NOIP 2005 普及组第二题
题解
#include <iostream> #include <vector> #include <algorithm> using namespace std; // 定义区间结构体 struct Interval { int left; int right; }; // 比较函数,用于按区间左端点排序 bool compare(const Interval& a, const Interval& b) { return a.left < b.left; } int main() { int l, n; cin >> l >> n; // 存储所有区间 vector<Interval> intervals(n); for (int i = 0; i < n; ++i) { cin >> intervals[i].left >> intervals[i].right; } // 按区间左端点排序 sort(intervals.begin(), intervals.end(), compare); // 合并重叠区间并计算移除树的总数量 int removed = 0; int currentLeft = intervals[0].left; int currentRight = intervals[0].right; for (int i = 1; i < n; ++i) { if (intervals[i].left <= currentRight) { // 区间重叠,更新当前合并区间的右端点 currentRight = max(currentRight, intervals[i].right); } else { // 区间不重叠,计算当前合并区间的长度并累加 removed += currentRight - currentLeft + 1; currentLeft = intervals[i].left; currentRight = intervals[i].right; } } // 处理最后一个合并区间 removed += currentRight - currentLeft + 1; // 计算剩余树的数量 int remaining = l + 1 - removed; cout << remaining << endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理