前缀和
一维前缀和
前缀和即前n项和。
题目中预处理前缀和之后,就可以快速地查询区间和了
部分代码如下
int n; //数组元素个数
int a[100003],s[100003];
cin>>n;
for (int i = 1; i <=n ; ++i) cin>>a[i];
//s[n]为前n项和(前缀和)
for (int j = 1; j <=n ; ++j) s[i]=s[i-1]+a[i];
//查询
//区间[l,r]的区间和
cout<<s[r]-s[l-1]<<endl;
二维前缀和
与一维前缀和基本相似,只是上升到了二维而已
算得的结果是矩阵的和
预处理前缀和过程
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]; //求前缀和
}
}
查询过程
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
printf("%d\n",s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]); //算部分和
差分
一维差分
差分可以被看成一种前缀和的逆运算,同时也把“区间操作”转化为差分序列上的“单点操作
对于一个给定的数列A,它的差分数列B定义为:
B[1]=A[1],B[i]=A[i]-A[i-1] (2<=i<=n)
插入函数
void insert(int l,int r,int c)
{
b[l]+=c;
b[r+1]-=c;
}
输出原数组
for(int i=1;i<=n;i++) b[i]+=b[i-1];
for(int i=1;i<=n;i++) printf("%d ",b[i]);
二维差分
与一维差分基本相似,只是上升到了二维而已
具体操作如下
插入操作
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;
}
输出原数组操作
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");
}