差分
差分和前缀和是密不可分的,如有一个数组a,就会对应有一个差分数组b。差分数组b的特性是:
a[i]=b1+b2+b3+…+bi,即为将数组a看做b的前缀和数组,a与b互为逆运算.
一维差分
简单分析
一维差分就是由一维数组组成的差分,主要运用差分数组的特性将求原数组a(b的前缀和数组)的某子区间进行加减操作从O(n)转化为O(1).
如:输入一个长度为 n 的整数序列。接下来输入 m 个操作,每个操作包含三个整数 l,r,c,表示将序列中 [l,r]之间的每个数加上 c。请你输出进行完所有操作后的序列。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<iostream> #include<stdio.h> using namespace std; #define N 100010 int a[N],b[N]; void insert(int l,int r,int num){ b[l] += num; b[r+1] -= num; } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); insert(i,i,a[i]); } while(m--){ int l,r,c; scanf("%d%d%d",&l,&r,&c); insert(l,r,c); } for (int i = 1; i <= n; ++i) { a[i] = a[i-1] + b[i]; printf("%d ",a[i]); }
return 0; }
|
二维差分
简单分析
二维差分与一维类似只不过由线段变为矩阵,差分数组b变为一个矩阵,作用依然是运用差分数组的特性将求原数组a(b的前缀和数组)的某子区间进行加减操作从O(n)转化为O(1).
如:输入一个 n 行 m 列的整数矩阵,再输入 q个操作,每个操作包含五个整数 x1,y1,x2,y2,c其中 (x1,y1)(x1,y1) 和 (x2,y2)(x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。每个操作都要将选中的子矩阵中的每个元素的值加上 c。请你将进行完所有操作后的矩阵输出。
代码
差分公式分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include <iostream> #include <stdio.h> using namespace std; #define N 1010 int a[N][N],b[N][N];
void insert(int x1,int y1,int x2,int y2,int c){ b[x1][y1] += c; b[x2 + 1][y1] -= c; b[x1][y2 + 1] -= c; b[x2 + 1][y2 + 1] += c; }
int main(){ int n,m,q; scanf("%d%d%d",&n,&m,&q); for(int i = 1;i <= n;i++){ for (int j = 1; j <= m; ++j) { scanf("%d",&a[i][j]); insert(i,j,i,j,a[i][j]); } } while(q--){ int x1,y1,x2,y2,c; scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c); insert(x1,y1,x2,y2,c); } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { a[i][j] =a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + b[i][j]; printf("%d ",a[i][j]); } printf("\n"); } return 0; }
|