题目
排序,区间合并
思路
一道经典的区间合并题,直接给出思路:
- 首先将给定的所有区间按区间左端点从小到大排序,然后遍历排序好之后的数组,维护当前合并后的区间的左端点和右端点。
- 如果遍历到的区间左端点大于当前合并后的区间的右端点,则说明已经合并好了一个区间,则将当前合并后的区间的左端点更新为当前遍历到的区间左端点,将当前合并后的区间的右端点更新为当前遍历到的区间右端点,将总的树的棵树减去刚刚合并好的区间内的树的棵树即可;
- 如果遍历到的区间左端点小于等于当前合并后的区间的右端点,则说明当前遍历到的区间可以合并到当前正在维护的合并后的区间里面,更新当前合并后的区间的右端点即可
代码
#include <stdio.h>
#include <stdlib.h>
// 自定义数组 a[n][2] 的排序函数
int cmp(const void* a, const void* b) {
int(*aa)[2] = (int(*)[2])a;
int(*bb)[2] = (int(*)[2])b;
// 只关心区间左端点从小到大排序即可
return (*aa)[0] - (*bb)[0];
}
int main(void) {
int n = 0, t = 0;
scanf("%d%d", &n, &t);
if (!t) {
// 如果没有任何需要移除的树,则返回所有树的棵树即可
printf("%d\n", n + 1);
return 0;
}
int a[t][2], i = 0;
for (i = 0; i < t; i++) {
scanf("%d%d", &a[i][0], &a[i][1]);
}
qsort(a, t, sizeof(int[2]), cmp);
int l = a[0][0], r = a[0][1];
// 注意树的区间是 [0, n]
n++;
for (i = 1; i < t; i++) {
if (a[i][0] > r) {
n -= r - l + 1;
l = a[i][0];
r = a[i][1];
}
if (a[i][1] > r) r = a[i][1];
}
// 别忘了最后一个区间
n -= r - l + 1;
printf("%d\n", n);
return 0;
}