一、一维前缀和
1、注意源数组都是从1开始的,(a1+a10)=S10-S0,这时候用到S0,定义S0=0;
#include<bits/stdc++.h>
//求一组数任意一个区间的数字之和
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],s[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d",s[r]-s[l-1]);
}
}
提高cin速度的方法:有这句话就不能用scanf了,大于100万用scanf
ios::sync_with_stdio(false);
二、二维前缀和
1、确定左上角和右下角后的矩阵内的数据的和。
构造前缀和数组的递推公式:
计算某一矩阵的数字之和:
#include<bits/stdc++.h>
//求一组数任意一个区间的数字之和
using namespace std;
const int N=1e5+10;
int n,m,q;
int a[N][N],s[N][N];
int main()
{
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]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=s[i-1][j]+s[i][j-1]-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",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][x2-1]);
}
}
三、一维差分
1、b是a的差分,b数组求前缀和得到a数组
2、如果让a的某个区间整体加c操作,让b[l]+c,b[r+1]-c即可实现;
3、因为这种方式O(n)->O(1)
#include<bits/stdc++.h>
//797差分
using namespace std;
const int N=1e6+10;
int b[N];
void insert(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int num;
scanf("%d",&num);
insert(i,i,num);//相当于让(i,i)区间同时加c
}
while(m--)
{
int l,r,num;
scanf("%d%d%d",&l,&r,&num);
insert(l,r,num);
}
for(int i=1;i<=n;i++)b[i]+=b[i-1];//原地求前缀和即原数组
for(int i=1;i<=n;i++)printf("%d",b[i]);
}
四、二维差分
1、二维差分:让某个子矩阵加某个值;一维差分:让某一段加某个值
2、让某个矩形整体加c,让左上角加c,然后看影响哪些部分,再调整矩形外部的部分抵消影响。
#include<bits/stdc++.h>
//798差分矩阵
using namespace std;
const int N=1e3+10;
int a[N][N],b[N][N];
int n,m,q;
void insert(int x1,int y1,int x2,int y2,int c)
{
b[x1][y1]+=c;
b[x1][y2+1]-=c;
b[x2+1][y1]-=c;
b[x2+1][y2+1]+=c;
}
int main()
{
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]);
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,num;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&num);
insert(x1,y1,x2,y2,num);
}
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]);
puts("");
}
return 0;
}