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;
}
代码解释:
- 输入处理:
- 首先读取学生数量
n和增加分数的次数p。 - 接着使用
vector存储每个学生的初始成绩。 - 再创建一个长度为
n + 1的差分数组diff,并初始化为 0。
- 首先读取学生数量
- 区间修改:
- 循环
p次,每次读取区间[x, y]和要增加的分数z。 - 在差分数组中,将
diff[x - 1]加上z,如果y小于n,则将diff[y]减去z。
- 循环
- 还原数组:
- 通过前缀和的方式将差分数组还原为修改后的成绩数组。从第二个元素开始,
diff[i]等于它本身加上diff[i - 1],同时将这个差值加到scores[i]上。 - 对于第一个元素,直接将
diff[0]加到scores[0]上。
- 通过前缀和的方式将差分数组还原为修改后的成绩数组。从第二个元素开始,
- 找出最低分:
- 使用
min_element函数找出scores数组中的最小值。
- 使用
- 输出结果:
- 输出修改后的最低分。
浙公网安备 33010602011771号