前缀和,差分
一维前缀和
为了方便计算区间和,所以下标从1开始
#include <iostream>
using namespace std;
const int maxn=1e6+5;
int q[maxn];
int main(){
int n,m;
cin>>n>>m;
q[0]=0;
for(int i=1;i<=n;++i){
int a;cin>>a;//输入n个数
q[i]=q[i-1]+a;//前缀和数组
}
while(m--){
int x,y;
cin>>x>>y;
cout<<q[y]-q[x-1]<<endl;
}
return 0;
}
二维前缀和
#include <iostream>
using namespace std;
const int N = 1010;
int a[N][N], s[N][N];
int main() {
int n, m, q;
cin >> n >> m >> q;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", &a[i][j]);
s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j]; // 求前缀和
}
while (q--) {
int x1,y1,x2,y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
// 算子矩阵的和
printf("%d\n", s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]);
}
return 0;
}
一维差分
如果数组b的前缀和得到的数组是a,那么b[0]=a[0],b[1]=a[1]-a[0],b[2]=a[2]-a[1];
对于要插入的数组a,它的差分数组等于本身(原理为,默认a,b数组都为0,那么a数组即为b数组的前缀和,b数组即是差分数组,对于差分数组,如果只是插入一个数,其实不影响差分数组;**
#include<iostream>
using namespace std;
const int N = 1e6+5;
int a[N], b[N];
void insert(int l , int r , int x){
b[l] += x;
b[r + 1] -= x;
}
int main(){
int n , m;
cin >> n >> m;
for(int i = 1; i <= n; i++) cin>>a[i];
for(int i = 1; i <= n; i++) insert(i,i,a[i]); //这一步是改变b,使得b仍然是a的差分数组
while(m--){//这一步是主要操作,通过操作差分数组b,间接使得把a数组【l,r】里面的数全部加上c
int l, r,c;
cin>>l>>r>>c;
insert(l,r,c);
}
//差分数组b的前i项和就是a【i】
for(int i = 1; i <= n; i++) b[i] = b[i - 1] + b[i]; //把b数组前i项求和,这时候b【i】就变成了a【i】
for(int i = 1; i <= n; i++) a[i] = b[i]; //把b【i】赋给a【i】
for(int i = 1; i<=n; i++)cout<<a[i]<<" ";
return 0;
}
二维差分
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
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;
cin >> n >> m >> q;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
insert(i, j, i, j, a[i][j]); //构建差分数组
}
}
while (q--)
{
int x1, y1, x2, y2, c;
cin >> 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++)
{
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; //二维前缀和
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
printf("%d ", b[i][j]);
}
printf("\n");
}
return 0;
}