差分数组与前缀和
Posted mrpeng2333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了差分数组与前缀和相关的知识,希望对你有一定的参考价值。
前缀和
前缀和顾名思义就是前面i个数的总和。
假设有一个序列A,前缀和为S。根据概念很容易知到公式
\(S[i]=\displaystyle \sum_j=1^iA[j]\)如何求区间\([l,r]\)的和呢?
\(sum[l,r]=s[r]-s[l-1]\)那如果要对多个不同区间
\([l,r]\)进行加减操作呢?然后输出某个区间\([l,r]\)的区间和,接下来就要用到差分数组了
差分数组
设原数组为\(A[i]\),差分数组为\(B[i]\),则:
\[B[i]=\begincases A[i]&i=1\\ A[i]-A[i-1]&i\geq2 \endcases\]
差分数组的性质:
如果对区间\([l,r]\)进行修改,只需修改\(B[l],B[r+1]\)(\(B[l]\)加上修改值,\(B[r+1]\)减去修改值)
\(A[i]=\displaystyle \sum_j=1^iB[j]\)(通过\(B[i]=A[i]-A[i-1]\)证明)
$S[x]=\displaystyle \sum_i=1^xA[i]=\displaystyle \sum_i=1^x \displaystyle \sum_j=1^iB[j]=\displaystyle \sum _i=1^x(x-i+1)*B[i] $
有n个数。m个操作,每一次操作,将x~y区间的所有数增加z;
最后有q个询问,每一次询问求出x~y的区间和。
设原数组为\(A[i]\)
步骤:
- 先求出差分数组\(B[i]=A[i]-A[i-1]\)
- 在根据\(m\)个造作修改\(B[i]\)
- 求修改后的\(A[i]=A[i-1]+B[i]\)
- 求前缀和\(S[i]=S[i-1]+A[i]\)
- 最后输出区间和\(sum[x,y]=S[y]-S[x-1]\)
举个栗子 航班预订统计
这道题很简单,没有要求输出区间和,也不用先求出差分数组
#include<iostream>
using namespace std;
int n; //n个航班
int i; //i条预定记录
int b[20005]; //差分数组
int main()
cin>>n>>i;
for(int j=0;j<i;j++)
int x,y,z; //[x,y]预定了z个座位
cin>>x>>y>>z;
b[x]+=z;
b[y+1]-=z;
for(int k=1;k<=n;k++)
b[i]+=b[i-1];
cout<<b[i]<<' ';
前面都是一维前缀和,再举个一位前缀和的栗子 最大子矩阵
没有涉及区间修改,只是求前缀和
#include<iostream>
#include<algorithm>
using namespace std;
int m,n; //整数矩阵
int x,y; //所求子矩阵的长和宽
int b[1000][1000];
int ans;
int main()
cin>>m>>n>>x>>y;
int t;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
cin>>t;
b[i][j]+=b[i-1][j]+b[i][j-1]+b[i-1][j-1]+t;
if(i>=x&&j>=y)
ans=max(ans,b[i][j]-b[i-x][j]-b[i][j-y]-b[i-x][j-y]);
cout<<ans<<endl;
以上是关于差分数组与前缀和的主要内容,如果未能解决你的问题,请参考以下文章