一篇文章讲明白差分
题目
输入一个长度为 n 的整数序列。
接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r] 之间的每个数加上 c。
请你输出进行完所有操作后的序列。
输入格式
第一行包含两个整数 n 和 m。
第二行包含 n 个整数,表示整数序列。
接下来 m 行,每行包含三个整数 l,r,c,表示一个操作。
输出格式
共一行,包含 n 个整数,表示最终序列。
数据范围
1≤n,m≤100000,
1≤l≤r≤n,
−1000≤c≤1000,
−1000≤整数序列中元素的值≤1000
输入样例:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
输出样例:
3 4 5 3 4 2
讲解
1.差分是求前缀和的逆操作,对于原数组a[n],构造出一个数组b[n],使a[n]为b[n]的前缀和。
2.一般用于快速对整个数组进行操作,比如对将a数组中[l,r]部分的数据全部加上c。使用暴力枚举的方法的话,时间复杂至少为O(n),而使用差分算法可以将时间复杂度降低到O(1)。
构造数组如下:
a[0 ]= 0; b[1] = a[1] - a[0]; b[2] = a[2] - a[1]; b[3] =a [3] - a[2]; ........ b[n] = a[n] - a[n-1];
构造代码
for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i] = a[i] - a[i - 1]; //构建差分数组 }
完整提交代码:
import java.io.*; import java.util.*; public class Main { static int N = 100010; static int [] a = new int [N]; static int [] b = new int [N]; static void insert(int l, int r, int c) { b[l] += c; b[r + 1] -= c; } public static void main(String[] args) throws IOException{ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String [] strs = reader.readLine().trim().split(" "); int n = Integer.parseInt(strs[0]); int q = Integer.parseInt(strs[1]); strs = reader.readLine().trim().split(" "); for (int i = 1; i <= n; ++ i) { a[i] = Integer.parseInt(strs[i - 1]); insert(i, i, a[i]); } while(q -- > 0) { int l, r, c; strs = reader.readLine().trim().split(" "); l = Integer.parseInt(strs[0]); r = Integer.parseInt(strs[1]); c = Integer.parseInt(strs[2]); insert(l, r, c); } for (int i = 1; i <= n; ++ i) a[i] = a[i - 1] + b[i]; for (int i = 1; i <= n; ++ i) System.out.print(a[i] + " "); } }