输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
解题思路:
差分数组:实际是前缀和数组的逆过程,用于频繁对某段连续区间修改(同时加m或同时减m). 时间复杂度O(1).
从原数组求解差分数组(初始化差分数组):b[i] = a[i] - a[i - 1] (i ≥ 1)
从表格的第二行向第三行看是得到了差分数组;从第三行向第二行看是得到了前缀和数组。
当对原数组的某一段区间连续加一个数时,例如将[2,5]的值都加3得到:
可以看出:在差分数组上只是左端点L的值加3,右端点R+1的值减3,在差分数组b[L+1,R]的值并没有发生变化。但是时间复杂度从遍历原数组的O(n)优化到只改变端点值的O(1).
从差分数组得到原数组:只需要将差分数组看成原数组,在此基础上求前缀和数组即可得到:a[i] = a[i -1] + b[i]
Java代码:
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] split = br.readLine().split(" ");
int n = Integer.parseInt(split[0]);
int m = Integer.parseInt(split[1]);
int []a = new int[n + 2];
int []b = new int[n + 2];//预留出首尾两个位置
split = br.readLine().split(" ");
for(int i = 1; i <= n; i++) {
a[i] = Integer.parseInt(split[i - 1]);
b[i] = a[i] - a[i - 1];//初始化差分数组
}
for(int i = 0; i < m; i++) {
split = br.readLine().split(" ");
int l = Integer.parseInt(split[0]);
int r = Integer.parseInt(split[1]);
int v = Integer.parseInt(split[2]);
b[l] += v;
b[r + 1] -= v;
}
for(int i = 1; i <= n; i++) {
a[i] = a[i - 1] + b[i];//通过差分数组求原数组(前缀和数组)
System.out.print(a[i] + " ");
}
}
}