前缀和与差分
如果给出一串长度为n的数列,再给出m个询问,每次询问给出L,R两个数,要求给出区间[L,R]里的数的和。对于m次询问,如果每次都遍历一遍区间内的值并累加,其时间复杂度为O(nm),如果数据量稍大一点就有可能超时,如果使用前缀和的方法,就能够将时间复杂度降到O(n+m),节省了运算时间。
-
一维前缀和 —— 模板题 AcWing 795. 前缀和
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[100009];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];
}
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
cout<<a[y]-a[x-1]<<endl;
}
return 0;
} -
一维差分——AcWing 797.差分
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[102009],b[100099];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++)
{
int x,y,v;
cin>>x>>y>>v;
b[x]+=v;
b[y+1]-=v;
}
for(int i=1;i<=n;i++)
b[i]+=b[i-1];
for(int i=1;i<=n;i++)
cout<<a[i]+b[i]<<" ";
return 0;
} -
二维矩阵——Acwing 798 子矩阵的和
#include<bits/stdc++.h>
using namespace std;
int n,q,m;
int a[1001][1001],sum[1001][1001];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j]; //前缀和
}
for(int i=1;i<=q;i++)
{
int x,y,xx,yy;
cin>>x>>y>>xx>>yy;
int num=sum[xx][yy]-sum[x-1][yy]-sum[xx][y-1]+sum[x-1][y-1];
cout<<num<<endl;
}
return 0;
} -
Acwing 799.差分矩阵
#include<bits/stdc++.h>
using namespace std;
int n,q,m;
int sum[1001][1001],b[1001][1001];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>sum[i][j];
for(int i=1;i<=q;i++)
{
int x,y,xx,yy,v;
cin>>x>>y>>xx>>yy>>v;
b[x][y]+=v;
b[x][yy+1]-=v;
b[xx+1][y]-=v;
b[xx+1][yy+1]+=v;
}
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++)
cout<<sum[i][j]+b[i][j]<<" ";
cout<<endl;
}
return 0;
}