P2367 语文成绩——差分、前缀和

题目背景

语文考试结束了,成绩还是一如既往地有问题。

题目描述

语文老师总是写错成绩,所以当她修改成绩的时候,总是累得不行。她总是要一遍遍地给某些同学增加分数,又要注意最低分是多少。你能帮帮她吗?

输入格式

第一行有两个整数 \(n\)\(p\),代表学生数与增加分数的次数。

第二行有 \(n\) 个数,\(a_1 \sim a_n\),代表各个学生的初始成绩。

接下来 \(p\) 行,每行有三个数,\(x\)\(y\)\(z\),代表给第 \(x\) 个到第 \(y\) 个学生每人增加 \(z\) 分。

输出格式

输出仅一行,代表更改分数后,全班的最低分。

输入输出样例 #1

输入 #1

3 2
1 1 1
1 2 1
2 3 1

输出 #1

2

说明/提示

对于 \(40\%\) 的数据,有 \(n \le 10^3\)

对于 \(60\%\) 的数据,有 \(n \le 10^4\)

对于 \(80\%\) 的数据,有 \(n \le 10^5\)

对于 \(100\%\) 的数据,有 \(n \le 5\times 10^6\)\(p \le n\),学生初始成绩 $ \le 100\(,\)z \le 100$。

题解

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n, p;
    // 读取学生数量 n 和增加分数的次数 p
    cin >> n >> p;

    // 存储每个学生的初始成绩
    vector<int> scores(n);
    for (int i = 0; i < n; ++i) {
        cin >> scores[i];
    }

    // 初始化差分数组,长度为 n + 1,初始值都为 0
    vector<int> diff(n + 1, 0);

    // 进行区间修改操作
    for (int i = 0; i < p; ++i) {
        int x, y, z;
        cin >> x >> y >> z;
        // 差分数组区间修改,注意下标从 0 开始,所以 x - 1
        diff[x - 1] += z;
        if (y < n) {
            diff[y] -= z;
        }
    }

    // 还原修改后的成绩数组
    for (int i = 1; i < n; ++i) {
        diff[i] += diff[i - 1];
        scores[i] += diff[i];
    }
    scores[0] += diff[0];

    // 找出最低分
    int min_score = *min_element(scores.begin(), scores.end());

    // 输出结果
    cout << min_score << endl;

    return 0;
}

代码解释:

  1. 输入处理
    • 首先读取学生数量 n 和增加分数的次数 p
    • 接着使用 vector 存储每个学生的初始成绩。
    • 再创建一个长度为 n + 1 的差分数组 diff,并初始化为 0。
  2. 区间修改
    • 循环 p 次,每次读取区间 [x, y] 和要增加的分数 z
    • 在差分数组中,将 diff[x - 1] 加上 z,如果 y 小于 n,则将 diff[y] 减去 z
  3. 还原数组
    • 通过前缀和的方式将差分数组还原为修改后的成绩数组。从第二个元素开始,diff[i] 等于它本身加上 diff[i - 1],同时将这个差值加到 scores[i] 上。
    • 对于第一个元素,直接将 diff[0] 加到 scores[0] 上。
  4. 找出最低分
    • 使用 min_element 函数找出 scores 数组中的最小值。
  5. 输出结果
    • 输出修改后的最低分。
posted @ 2025-02-19 10:02  ToFuture$  阅读(30)  评论(0)    收藏  举报