语文成绩(洛谷)

题目

原题

题目背景

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

题目描述

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

输入格式

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

第二行有 n n n 个数, a 1 ∼ a n a_1 \sim a_n a1an,代表各个学生的初始成绩。

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

输出格式

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

样例 #1

样例输入 #1


3 2 1 1 1 1 2 1 2 3 1

样例输出 #1

2

提示

对于 40 % 40\% 40% 的数据,有 n ≤ 1 0 3 n \le 10^3 n103

对于 60 % 60\% 60% 的数据,有 n ≤ 1 0 4 n \le 10^4 n104

对于 80 % 80\% 80% 的数据,有 n ≤ 1 0 5 n \le 10^5 n105

对于 100 % 100\% 100% 的数据,有 n ≤ 5 × 1 0 6 n \le 5\times 10^6 n5×106 p ≤ n p \le n pn,学生初始成绩 $ \le 100 , , z
\le 100$。

思路

这里的思路是差分。因为直接模拟的话时间会爆。
离散化操作就是生成一个新的数组。每个元素都是由原数组当前位置减去元素组上一个位置得到( b [ i ] = a [ i ] − a [ i − 1 ] b[i]=a[i]-a[i-1] b[i]=a[i]a[i1])。特别的新的数组第一个元素就是其本身因为第一个元素前面没有元素。新的数组的前缀和得到的就是原数组。
例如新数组第一个元素和第二个元素相加,第二个元素是第二个和第一个元素的差值,这个差值加上第一个元素原数组第一个元素很明显就是等于第二元素本身,而新数组里第一个元素和原数组第一个元素恰好相等。同理新数组第三个元素是原数组第三个和第二个元素差值。而新数组第一个和第二个元素相加等于原第二元素,这样第一二三个元素相加就是等于原数组第三个元素。这就是前缀和等于原数组。
这里的新数组有什么好处呢。好处在于在新数组上任意位置加上某个数,该位置后面元素全会加上这个数。在上面例子中如果在第二个位置减去1,那么根据前缀和计算出来的第二个元素会比原数组小1,而第三个元素也需要加上第二个元素,也就是说第三个元素也会比原数组第三个元素小于1.如果后面还有元素又会继续小1。
那如果希望某个区间加上某个值,这里只需要在右界减去同一个值。这样右边超过区域的位置原本加上的值就会被这个减去的值抵消。这样可以大大减少时间消耗。因为改一个区域只需要改元素两个位置。如果是直接模拟区间一旦变大就会消耗大量时间。

代码

#include
using namespace std;
int d[5000001];
int de[5000001];
int main(){
	int m,n;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>d[i];
		de[i]=d[i]-d[i-1];
	}
	int x,y,z;
	for(int j=1;j<=m;j++){
		cin>>x>>y>>z;
		de[x]+=z;			//左边界加z
		de[y+1]-=z;			//右边界减z
	}
	int mins=9999999;
	for(int i=1;i<=n;i++){	//前缀和还原数组
		d[i]=de[i]+d[i-1];
		if(d[i]<mins)
		mins=d[i];
	}
	cout<<mins;
} 

你可能感兴趣的:(算法)