前缀和与差分【洛谷】P2367语文成绩
前缀和:可以理解为数学上的数列的前n项和
差分:可以看作前缀和的逆运算
前缀和与差分有一维、二维
举例【洛谷】P2367语文成绩
题目描述
语文老师总是写错成绩,所以当她修改成绩的时候,总是累得不行。她总是要一遍遍地给某些同学增加分数,又要注意最低分是多少。你能帮帮她吗?
输入格式
第一行有两个整数 nn,pp,代表学生数与增加分数的次数。
第二行有 nn 个数,a_1 \sim a_na1∼a**n,代表各个学生的初始成绩。
接下来 pp 行,每行有三个数,xx,yy,zz,代表给第 xx 个到第 yy 个学生每人增加 zz 分。
输出格式
输出仅一行,代表更改分数后,全班的最低分。
输入输出样例
输入 #1
3 2
1 1 1
1 2 1
2 3 1
输出 #1
2
具体理解看代码
#include <stdio.h>
int n,p,score[5000010],a[5000010],s,left,right,min;//声明变量
//由于数组数据较多,建议放在main函数外面,避免爆栈
int main() {
scanf("%d%d",&n,&p); //分别代表学生个数以及增加的次数
score[0]=0;a[0]=0; //方便后文计算
for(int i=1;i<=n;i++){ //输入n个学生的初始成绩
scanf("%d",&score[i]); //为了使用差分,把初始分数作为前缀和
a[i]=score[i]-score[i-1]; //构造差分数组,当然把这个过程放在循环里面,减小了开销,再开一个循环也可以
}
for(int i=1;i<=p;i++){ //根据输入,修改分数
scanf("%d%d%d",&left,&right,&s);
a[left]+=s;a[right+1]-=s; //差分思想的精髓在这里,对一组数组差分后,再求前缀和,可以大大减小时间复杂度
}
min=a[1];
for(int i=2;i<=n;i++){
a[i]+=a[i-1];
if(a[i]<min) //求最低分数
min=a[i];
} //最后a[i]里的数,存放的就是分数
printf("%d",min);
return 0;
}