【多解 · 代码超详解】CometOJ C0180 [2005普及组-B]校门外的树【离散化处理区间并】

一、题目描述

题目描述

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

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

输入描述

第一行有两个整数:L(1 ≤ L ≤ 10 000)和 M(1 ≤ M ≤ 100),L 代表马路的长度,M 代表区域的数目,L 和 M 之间用一个空格隔开。接下来的 M 行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。

输出描述

包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

样例输入 1

500 3
150 300
100 200
470 471

样例输出 1

298

提示

【数据规模】

对于20%的数据,区域之间没有重合的部分;

对于其它的数据,区域之间有重合的情况。

二、算法分析说明与代码编写指导

法一:

本题数据规模不太大,可以直接暴力模拟,时间复杂度约为 O(mn) 。

法二:

将输入的区间 [x, y] 输入有序对数组 p,并按 x 升序排序。设有序对 q ,N 为剩余的树的总数。
先令 q = p[0] 。接下来枚举剩下的区间 [xi, yi] 。
①如果 xi <= q.first ,就将两个区间合并,即令 q.second = max(q.second, yi) 。
②当枚举到的区间 pi 的左端点已经超出 q 的右端点时,将区间 q 换成 pi 。
重复如上两步直到枚举完毕,区间 q 经过(覆盖过)的全部区间就是要移走树的区间。
通过代码实现时,可以在 q 变动时先将 L 减去 q 覆盖的树的数量,也就是先移走这一批树,然后再统计接下来还需要移走哪些区间的树。容易验证,循环退出时,无论最后一个区间是否与 q 重叠,最后一个区间的树木数量均不会在循环中被减去(因为对 q 表示的区间移动时,被移走的树木是 q 变动之前的那一段),所以要把这一部分树木的数量也扣除。输出的时候,注意位置 0 也有一棵树,所以总数量要加 1 。
该方法的时间复杂度约为 O(m) 。

三、AC 代码

法一(1 ms):

#include
#include
#pragma warning(disable:4996)
using namespace std;
bitset<10001> b; unsigned L, M, x, y, n = 0;
int main() {
	scanf("%u%u", &L, &M);
	for (unsigned i = 0; i < M; ++i) {
		scanf("%u%u", &x, &y);
		for (unsigned j = x; j <= y; ++j)b[j] = 1;
	}
	for (unsigned i = 0; i <= L; ++i)if (b[i] == 0)++n;
	printf("%u\n", n);
	return 0;
}

法二(1 ms):

#include
#include
#include
using namespace std;
#pragma warning(disable:4996)
pair<unsigned, unsigned> p[100], q; unsigned L, M;
int main() {
	scanf("%u%u", &L, &M);
	for (unsigned i = 0; i < M; ++i)scanf("%u%u", &p[i].first, &p[i].second);
	sort(p, p + M); q = p[0];
	for (unsigned i = 1; i < M; ++i) {
		if (p[i].first <= q.second)q.second = max(q.second, p[i].second);
		else L -= q.second - q.first + 1, q = p[i];
	}
	L -= q.second - q.first + 1;
	printf("%u\n", L + 1);
	return 0;
}

虽然在本题中两种方法的耗时并无多少区别,但是当数据量非常大时,暴力模拟定会超时。所以希望大家能掌握第二种方法。

你可能感兴趣的:(ACM-ICPC)