题解:AtCoder AT_awc0044_c Range Addition

【题目来源】

AtCoder:C - Range Addition (atcoder.jp)

【题目描述】

Takahashi manages a sequence of \(N\) integers. The elements of the sequence are numbered from \(1\) to \(N\) from left to right, and initially all elements have a value of \(0\).
高桥管理一个包含 \(N\) 个整数的序列。序列的元素从左到右编号为 \(1\)\(N\),初始时所有元素的值均为 \(0\)

Takahashi performs \(M\) operations on this sequence. In the \(i\)-th operation, he adds \(1\) to the values of all elements whose indices are between \(L_i\) and \(R_i\), inclusive.
高桥对这个序列执行 \(M\) 次操作。在第 \(i\) 次操作中,他将所有索引在 \(L_i\)\(R_i\) 之间(含端点)的元素的值增加 \(1\)

After all operations have been performed, find the value of each element in the sequence.
所有操作完成后,求序列中每个元素的值。

【输入】

\(N\) \(M\)
\(L_1\) \(R_1\)
\(L_2\) \(R_2\)
\(\vdots\)
\(L_M\) \(R_M\)

  • The first line contains the number of elements in the sequence \(N\) and the number of operations \(M\), separated by a space.
  • The \((1 + i)\)-th line \((1 \leq i \leq M)\) contains the left endpoint \(L_i\) and right endpoint \(R_i\) of the interval for the \(i\)-th operation, separated by a space.

【输出】

Print \(N\) integers separated by spaces on a single line. The \(i\)-th integer \((1 \leq i \leq N)\) represents the value of the \(i\)-th element of the sequence after all operations have been performed.

【输入样例】

5 3
1 3
2 5
3 4

【输出样例】

1 2 3 2 1

【核心思想】

  1. 问题分析:给定长度为 \(N\) 的序列,初始所有元素为 \(0\),进行 \(M\) 次操作,每次将区间 \([L_i, R_i]\) 内的所有元素增加 \(1\)。求所有操作完成后每个元素的值。这是一个差分数组 + 前缀和问题,关键在于高效处理大量区间加法操作。

  2. 算法选择

    • 差分数组(Difference Array):将 \(M\) 个区间加 \(1\) 操作转化为 \(2M\) 个单点更新,实现 \(O(1)\) 区间标记
    • 前缀和还原:通过一次前缀和遍历,将差分数组还原为每个位置的实际值
    • 原地计算:使用同一个数组既存储差分值,又通过前缀和原地还原为最终值,空间高效
  3. 关键步骤

    • 初始化:数组 \(a[1..N]\) 初始为 \(0\)
    • 差分标记(处理 \(M\) 次操作):
      • 对于每次操作 \((L_i, R_i)\)
        • a[L_i]++:在左边界加 \(1\)
        • a[R_i + 1]--:在右边界后一个位置减 \(1\)(恢复后续位置)
    • 前缀和还原(计算每个位置的最终值):
      • 遍历 \(i\)\(1\)\(N\)a[i] = a[i-1] + a[i]
      • 此时 a[i] 表示位置 \(i\) 的最终值
    • 输出结果:依次输出 \(a[1]\)\(a[N]\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N + M)\),差分标记 \(O(M)\),前缀和还原 \(O(N)\)
    • 空间复杂度:\(O(N)\),只需要一个数组
  5. 差分数组的核心思想

    • 区间操作降维:差分数组将区间 \([l, r]\) 的加 \(1\) 操作转化为 a[l]++a[r+1]--,实现 \(O(1)\) 区间标记
    • 前缀和还原:通过前缀和将差分数组还原为实际值,a[i] 表示位置 \(i\) 被多少个区间覆盖
    • 原地计算优势:同一个数组既作为差分数组接收修改,又通过前缀和原地还原为最终数组,无需额外空间
    • 边界处理技巧:在 \(R_i + 1\) 处减 \(1\),确保只有区间内的位置受到影响
    • 适用于区间加减、区间覆盖次数统计类问题

【算法标签】

差分

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, m;  // n: 数组长度, m: 操作次数
int a[N];  // 差分数组
int main()
{
    cin >> n >> m;  // 输入数组长度和操作次数

    // 处理每个操作
    while (m--)
    {
        int l, r;
        cin >> l >> r;  // 输入区间[l, r]
        a[l]++;         // 左端点加1
        a[r + 1]--;     // 右端点后一位减1
    }

    // 计算前缀和,得到每个位置的最终值
    for (int i = 1; i <= n; i++)
    {
        a[i] = a[i - 1] + a[i];  // 前缀和
    }

    // 输出结果
    for (int i = 1; i <= n; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;

    return 0;
}

【运行结果】

5 3
1 3
2 5
3 4
1 2 3 2 1
posted @ 2026-06-14 10:43  团爸讲算法  阅读(9)  评论(0)    收藏  举报