本文主要是介绍P1047 [NOIP2005 普及组] Bailian2808 校门外的树【标记+差分】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
2808:校门外的树
描述
某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。
马路上有一些区域要用来建地铁,这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。
输入
输入的第一行有两个整数L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
输出
输出包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。
样例输入
500 3
150 300
100 200
470 471
样例输出
298
来源
noip2005普及组
问题链接:Bailian2808 校门外的树
问题描述:(略)
问题分析:
这是一个简单的问题,用一个数组标记一下树就可以了。需要移走的树也做过标记,然后再统计一下就得到结果了。关键是能否想到使用标记数组。
程序说明:
C语言程序中,标记数组tree[]使用char类型最为节省存储。如果使用C++语言编程则可以使用bool类型的数组。
为了在初始化数组tree[]时避免对整个数组进行初始化,使得初始化单元的数量更少,在读入l值后再进行初始化。通常的写法是"memset(tree, TRUE, sizeof(tree));"。
另外一种解法是差分法,整个数轴需要向右移动一个位置,因为需要处理0-L之间的数。
参考链接:(略)
题记:使用宏定义可以使得程序更加易于阅读。
AC的C语言程序(差分)如下:
/* Bailian2808 校门外的树 */#include <stdio.h>
#include <string.h>#define L 10000 + 3
int d[L], cnt[L];int main(void)
{int l, m, i;scanf("%d%d", &l, &m);memset(d, 0, l + 3);for(i = 1; i <= m; i++) {int start, end;scanf("%d%d", &start, &end);d[start + 1]++, d[end + 2]--;}int cnt2 = 0;cnt[0] = 0;for(i = 1; i <= l + 1; i++)if ((cnt[i] = cnt[i - 1] + d[i]) > 0)cnt2++;printf("%d\n", l + 1 - cnt2);return 0;
}
AC的C语言程序如下:
/* Bailian2808 校门外的树 */#include <stdio.h>
#include <string.h>#define TRUE 1
#define FALSE 0
#define L 10000char tree[L + 1];int main(void)
{int l, m, i, j;scanf("%d%d", &l, &m);memset(tree, TRUE, l + 1);for(i = 1; i <= m; i++) {int start, end;scanf("%d%d", &start, &end);for(j = start; j <= end; j++)tree[j] = FALSE;}int cnt = 0;for(i = 0; i <= l; i++)if(tree[i]) cnt++;printf("%d\n", cnt);return 0;
}
这篇关于P1047 [NOIP2005 普及组] Bailian2808 校门外的树【标记+差分】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!