前缀和准确来说并不是一种算法,应该算是一种思想,即如果要计算一个一维数组的[l,r]区间内的数的总和,可以计算该数组的所有前缀和数组s[ ],在使用s[l,r] = s[ l ] - s[r - 1]就可以计算这个数组之中的总和就可以了!
前缀和算法的模板(一维数组版)
int front_count(int l,int r,int q[]){
int s[];
for (int i = 1;i <= length(q);i++) s[i] = s[i - 1] + a[i];
//计算区间内的总和
return s[r] - s[l - 1];
}
前缀和的边界问题
1. 为什么使用s[ r ] - s[ l - 1]?
原因:主要为了不用判断是否到了最后一个数,因为前面一个数就是零,减去对结果并没有影响,这样设置的话就可以使得这个公式被所有的区间适用,不用进行边界问题的判断。
前缀和算模板二(二维数组版)、
int doubleFront_count(int x1,int y1,int x2,int y2,int q[][]){
int len = length(q);
int s[][];
//计算前缀和,主要是研究适用公式
for (int i =1;i <= len;i++){
for (int j= 1;j <= len;j++){
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
}
}
//直接使用x和y进行定位计算前缀和就可以了
return s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1][y1];
}
差分算法
差分算法准确来说也是这一种思想,就是前缀和的逆运算,前缀和是:s[i] = s[i - 1] + a[i];
而差分就是使用s数组来表示a[ i ];通过等式关系可以知道a[i] = s[i] - s[i- 1];
差分的作用
当需要对a数组的每一个数进行加某个一样的操作的时候,就可以通过差分数组的首元素的操作就可以将a数组的所有数加上这个数;
原因
核心思想:差分数组的前缀和就是原数组
设置数组b[ ]是a[ ]的差分数组,那么进行前缀和的时候,都会加上差分数组的第一个首元素,所以当第一个数组加上一个数的时候就会使得,后面的所有前缀和都要加上这个数,即原数组 a 的每一个数加上这个数,然后再后面一个数减去这个数,就可以将这个区间之后的所有数减去这个加数,这样就可以等到这个这个区间内的所有数加上一个数的结果了;
差分数组的模板(一维数组版本)
int[] differ_separate(int l,int r,int c){
int num[],b[i];
for (int i = q;i <= length(q);i++){
scanf("%d",&num[i]);
b[i]= num[i] - num[i - 1];
}
//直接将第一个数加c,区间的最后一个的下一个数减c就可以了
b[l] += c;
b[r + 1] -= c;
//使用前缀和等到处理之后的原数组
for (int i = l;i < =r;i) b[i] += b[ i - 1];
return b[];
}
二维差分数组
根据上面的前缀和的公式:s[ i ][ j ] = s[i - 1][ j ] + s[ i ][ j -1 ] - s[ i- 1 ][ j - 1 ] + a[ i ][ j ];
可以逆推出a[i][j] = s[ i ][ j ] - (s[i - 1][ j ] + s[ i ][j -1] - s[i- 1][j - 1]);
然后区间内第一个加上这个数,区间内最后一个数减去这个数就可以了
差分数组的模板(二维数组版)
void differ_double (int x1,int y1,int x2,int y2){
int a[][],b[][];
for (int i = 1;i <= length(a);i++)
for (int j = 1;j <= length(a[i]);j++)
scanf("%d",&a[i][j]);
//使用b数组求得a数组的差分数组
for (int i = 1;i <= length(a);i++)
for (int j = 1;j <= length(a[i]);j++)
b[i][j] = a[i][j] - a[i- 1][j] - a[i][j- 1] + a[i - 1][j- 1];
//使用差分数组的性质,在指定位置加上一个数,在将受影响的位置进行抵消 就可以了
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;
for (int i = 1;i <= length(a);i++)
for (int j = 1;j <= length(a[i]);j++)
a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i -1][j - 1] + b[i][j];
for (int i = 1;i <= length(a);i++)
for (int j = 1;j <= length(a[i]);j++)
printf("%d",a[i]j[j]);
}