题目:小明拥有 N 个彩灯,第 i 个彩灯的初始亮度为 ai。
小明将进行 Q次操作,每次操作可选择一段区间,并使区间内彩灯的亮度 +x(x 可能为负数)。
求 Q次操作后每个彩灯的亮度(若彩灯亮度为负数则输出 0)。
输入描述
第一行包含两个正整数 N,Q,分别表示彩灯的数量和操作的次数。
第二行包含 N 个整数,表示彩灯的初始亮度。
接下来 Q 行每行包含一个操作,格式如下:
l r x
,表示将区间 l∼r的彩灯的亮度 +x。
1≤N,Q≤5×105,0≤ai≤109,1≤l≤r≤N,−109≤x≤109
输出描述
输出共 1 行,包含 N 个整数,表示每个彩灯的亮度。
输入输出样例
示例 1
输入
5 3
2 2 2 1 5
1 3 3
4 5 5
1 1 -100
输出
0 5 5 6 10
解题思路+代码:
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt(); // 彩灯数量
int q = scan.nextInt(); // 操作次数
long[] light = new long[n + 1]; // 亮度数组
for (int i = 1; i <= n; i++) {
light[i] = scan.nextInt(); //记录下每个彩灯的初始亮度
}
long[] diff = new long[n + 2]; // 差分数组,防止数组下标越界
// 处理 q 次操作
for (int i = 0; i < q; i++) {
//区间l~r
int l = scan.nextInt();
int r = scan.nextInt();
//对彩灯的亮度进行操作 + x
int x = scan.nextInt();
diff[l] += x; //让第 l 位置及之后的灯开始增加 x
diff[r + 1] -= x; //让第 r+1 位置开始,把增加的 x 抵消,保证只影响 l 到 r
}
long add = 0;
for (int i = 1; i <= n; i++) {
//对每个彩灯调亮度(+diff[i])
add += diff[i];
light[i] += add;
}
for (int i = 1; i <= n; i++) {
System.out.print(Math.max(0, light[i])); // 负数取 0
if (i != n) System.out.print("\t");
}
System.out.println(); // 结尾换行,避免格式错误
scan.close();
}
}
总结:一道一维差分题,该题的关键难点在于如何让l~r的范围+x,并记录下相应下标彩灯亮度的变化。解决关键难点:题目要求的执行q次+x(调亮度)操作,那么对q进行遍历,每一次遍历时都要让l~r的范围+x, diff[l] += x;(让第 l 位置及之后的灯开始增加 x),diff[r + 1] -= x;(让第 r+1 位置开始,把增加的 x 抵消,保证只影响 l 到 r),这样便记录下了执行q次操作时对应彩灯索要调的亮度(一维差分,前缀和)。再遍历n个彩灯,使彩灯的初始亮度与所调的亮度相加,亮度为负数的设置为0,否则为相加之后的亮度。