当前位置: 首页 > article >正文

差分数组的使用

这个问题要求我们通过杨学长的超能力来在一条马路上种树,并计算最终种树的总长度。每次杨学长的超能力作用会覆盖一个区间,我们需要计算最终种树的总长度。

问题分析

给定一个马路长度为 n,有 m 次操作,每次操作会让某个区间 [l, r] 种上树。我们的任务是求出所有操作后,马路上最终种树的总长度(即被种树的区域的长度)。

思路

  1. 直接模拟每次操作:我们可以用一个布尔数组 tree[n] 来记录马路上每个位置是否被种树。每次操作时,将该区间内的所有位置标记为种树。
  2. 优化的思路:直接模拟每次操作会导致时间复杂度较高,尤其是当区间 [l, r] 很长时。因此,我们可以考虑使用 区间标记法,即使用一个辅助数组来记录区间的变化(类似差分数组),然后通过一次遍历得到最终结果。

优化方案

  1. 使用一个大小为 n + 1 的数组 tree 来记录每个位置是否种树。
  2. 对于每次操作 (l, r),我们可以:
    • 在 tree[l] 位置标记种树的开始(将 tree[l] 设置为 1)。
    • 在 tree[r + 1] 位置标记种树的结束(将 tree[r + 1] 设置为 -1,表示从 r + 1 开始就不再种树)。
  3. 最后我们通过一次遍历累加这个差分数组,计算哪些位置最终种了树。

代码实现

#include <stdio.h>

#define MAX_N 1000000

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    // 创建一个差分数组,初始值为 0
    int tree[MAX_N + 2] = {0};  // +2 是为了防止访问 tree[r + 1] 时越界
    
    // 处理每一个操作
    for (int i = 0; i < m; i++) {
        int l, r;
        scanf("%d %d", &l, &r);
        tree[l] += 1;        // 从 l 开始种树
        tree[r + 1] -= 1;    // 从 r+1 停止种树
    }
    
    // 统计最终种树的总长度
    int count = 0;
    int current = 0; // 当前的种树标记
    for (int i = 1; i <= n; i++) {
        current += tree[i];  // 更新当前标记
        if (current > 0) {   // 如果当前标记大于 0,表示这个位置种了树
            count++;
        }
    }
    
    // 输出结果
    printf("%d\n", count);
    
    return 0;
}

解释

  1. 输入处理

    • 通过 scanf 读取 n 和 m,其中 n 是马路的长度,m 是操作次数。
    • 接着,读取每次操作的区间 [l, r]
  2. 差分数组处理

    • 初始化一个大小为 n + 2 的数组 tree(多一个位置防止 r + 1 越界)。
    • 对于每个操作 (l, r),更新差分数组:
      • tree[l] += 1 表示从位置 l 开始种树。
      • tree[r + 1] -= 1 表示从位置 r + 1 开始停止种树。
  3. 统计种树的长度

    • 初始化一个变量 current 来记录当前位置是否种树。
    • 遍历 tree 数组,通过累加差分值来计算当前位置是否种树,如果是种树,增加种树长度的计数。
  4. 输出

    • 最后输出种树的总长度。

时间复杂度

  • 初始化和更新差分数组:每次操作只更新两个位置,因此每次操作的时间复杂度为 O(1),总共进行 m 次操作,所以时间复杂度为 O(m)
  • 计算最终种树长度:遍历一次长度为 n 的马路,时间复杂度为 O(n)

因此,总的时间复杂度为 O(n + m),在 n <= 1e6m <= 1000 的情况下,性能是足够的。

示例

输入:

100 2

1 3

2 5

输出:

5

解释:

  • 第一次操作 [1, 3],种树的区域是 1, 2, 3
  • 第二次操作 [2, 5],种树的区域是 2, 3, 4, 5
  • 最终种树的区域是 1, 2, 3, 4, 5,总长度是 5

http://www.kler.cn/a/445952.html

相关文章:

  • 初识面向对象晨考day09
  • 搜索召回概要
  • React图标库: 使用React Icons实现定制化图标效果
  • 使用 datamodel-code-generator 从 MySQL 生成 Python 模型
  • 楚慧杯-Web
  • SLURM资料
  • 工业主板产品线的多样性与应用
  • 【数据分析之pandas】
  • go语言学习之错误记录-1、GOPROXY
  • 原生开发vs混合开发
  • 【上传文件过大进行的切片式上传】
  • Oracle 表连接原理与优化
  • Qt 开发之蓝牙连接
  • hackme靶机保姆及攻略
  • elasticsearch Flattened 使用
  • JS面向对象及继承
  • 【第六节】Git Flow:分支管理模型与工作流程
  • nano编辑器怎么退出并保存
  • DeepFaceLab技术浅析(六):后处理过程
  • Golang中什么是协程泄露(Goroutine Leak)
  • autok3s管理k3s单节点集群
  • [Unity] 【VR】【游戏开发】在VR中使用New Input System获取按键值的完整教程
  • 【Jenkins】pipeline 的基础语法以及快速构建一个 jenkinsfile
  • sql server索引优化语句
  • Tomcat10安装报错Unknown module: java.rmi specified to --add-opens
  • nginx-虚拟主机配置笔记