c语言校门外的数

题目是这个样子的

某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。                                                                                                          由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。

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

输出描述

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

解题思路

题目说给定几个区域(这个区域有可能重复也有可能不重复),把这些区域的树挖了然后求剩下的树。那么不难想到,我们可

<think>我们正在解决“校门外的树”问题。根据引用[2][3][4],问题描述如下: 有一条长度为L的马路上种满了树,坐标从0到L(包括0和L)的整点都有树。 接下来有M个区域要建地铁,这些区域用起始点和终止点表示(区域可能有重叠),需要移走区域内的所有树(包括端点)。 目标是计算移走这些区域的树后,马路上剩余的树的目。 输入格式: 第一行:两个整L(马路长度)和M(区域目) 接下来的M行:每行两个整,表示一个区域的起始点和终止点 输出格式: 一个整,表示剩余树的目 注意:L最大为10000,M最大为100 思路: 我们可以用一个组表示马路上的每个点是否有树。初始化组,所有位置都有树(用0表示)。 对于每个区域,将其覆盖的区间内的树移走(标记为1,表示没有树)。 最后统计整个组(0到L)中值为0的位置的个,即剩余树的目。 参考引用[1][5]中的代码,我们可以这样实现: 步骤: 1. 定义一个长度至少为10001的组(因为L最大为10000,包括0到10000共10001个点),并初始化为0。 2. 读取L和M。 3. 循环M次,每次读取一个区域的起始点x和终止点y。 4. 将区间[x,y]内的组元素都设置为1(表示树被移走)。 5. 遍历组的0到L(包括L)的位置,统计值为0的元素的个。 6. 输出统计结果。 注意:区域可能有重叠,但因为我们只是标记为1,重复标记不影响结果。 参考引用[1]的代码,我们稍作调整(使用更清晰的变量名): </think>### C语言实现“校门外的树”问题解决方案 #### 问题描述 某校大门外长度为$L$的马路上有一排树,每两棵相邻的树间隔都是1米。马路可看作轴$[0, L]$,整点都有树。现给出$M$个建地铁区域(起始点$x$和终止点$y$),移除区域内所有树(包括端点),求剩余树的目[^2][^3][^4]。 #### 算法思路 1. **初始化标记组**:创建组`tree[10001]`(长度$L+1$)初始化为0,0表示有树 2. **标记移除区域**:对每个区间$[x,y]$,将对应组位置标记为1 3. **统计剩余树**:遍历$[0,L]$区间,统计标记为0的位置量 #### 完整代码实现 ```c #include <stdio.h> int main() { int L, M; // L:马路长度, M:区域 scanf("%d %d", &L, &M); int tree[10001] = {0}; // 初始化所有位置有树(0) int removed_count = 0; // 被移除的树计 // 处理M个区域 for (int i = 0; i < M; i++) { int start, end; scanf("%d %d", &start, &end); // 标记移除区域 for (int j = start; j <= end; j++) { if (tree[j] == 0) { // 避免重复计 tree[j] = 1; // 标记为移除 removed_count++; // 计增加 } } } // 计算剩余树 = 总树 - 被移除树 int remain = (L + 1) - removed_count; printf("%d", remain); return 0; } ``` #### 复杂度分析 | 操作 | 时间复杂度 | 空间复杂度 | |----------------|----------------|----------| | 初始化组 | $O(L)$ | $O(L)$ | | 标记移除区域 | $O(M \cdot \text{avg})$ | - | | 统计结果 | $O(1)$ | - | > $\text{avg}$表示区域平均长度,$M$最大为100,$L$最大为10000 #### 测试案例 输入: ``` 500 3 150 300 100 200 470 471 ``` 输出: ``` 298 ``` #### 算法优化 1. **差分组优化**:当$L$很大时(如$L>10^6$),使用差分组可将时间复杂度降为$O(M+L)$ ```c // 差分组实现 int diff[10002] = {0}; // 比L多2个元素 for (int i=0; i<M; i++) { scanf("%d%d", &x, &y); diff[x]++; // 区间开始+1 diff[y+1]--; // 区间结束-1 } int sum = 0, remain = 0; for (int i=0; i<=L; i++) { sum += diff[i]; if(sum == 0) remain++; // 未被覆盖的位置 } ``` 2. **区间合并优化**:先合并重叠区间再标记,减少重复操作 #### 关键点说明 - **组长度**:必须为$L+1$(从0到$L$共$L+1$棵树)[^3] - **边界处理**:区域端点包含在内(如$[150,300]$包含150和300位置的树) - **重叠处理**:使用标记法自动处理区间重叠,无需额外逻辑[^5] ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值