1、前缀和(一维,二维)
应用:
一维:快速求一段连续子序列的和
二维:快速求一个子矩阵的和
//一维前缀和
const int N = 1e5+5;
int n,q,a[N],s[N];//a是原数组,s是前缀和数组
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i], s[i]=s[i-1]+a[i];
while(q--)//q次询问
{
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;//计算区间[l,r]的和
}
return 0;
}
//二维前缀和
const int N = 1e3+5;
int n,m,q,a[N][N],s[N][N];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
}
while(q--)//q次询问
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
cout<<s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<<endl;//计算以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的和
}
return 0;
}
2、差分(一维,二维)
应用:
一维:对于数组中[l,r]快速进行修改操作
二维:对于子矩阵快速进行修改操作
//一维差分
const int N = 1e5+5;
int n,q,a[N],diff[N];//diff差分数组
int main()
{
cin>>n>>q;
//构造差分数组
for(int i=1;i<=n;i++) cin>>a[i],diff[i]=a[i]-a[i-1];
while(q--)//q次修改操作
{
int l,r,c;
cin>>l>>r>>c;
//此处操作等价于将区间[l,r]内每个数加c
diff[l]+=c;
diff[r+1]-=c;
}
//由差分数组求原数组
for(int i=1;i<=n;i++) a[i]=diff[i]+a[i-1];
for(int i=1;i<=n;i++) cout<<a[i]<<" ";cout<<endl;
return 0;
}
//二维差分
const int N = 1e3+5;
int n,m,q,a[N][N],diff[N][N];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)//构造差分数组
cin>>a[i][j], diff[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
while(q--)//q次修改操作
{
int x1,y1,x2,y2,c;
cin>>x1>>y1>>x2>>y2>>c;
//差分数组的子矩阵修改操作,等价与将以(x1,y2)为左上角,(x2,y2)为右下角的每一个数加上c
diff[x1][y1]+=c;
diff[x1][y2+1]-=c;
diff[x2+1][y1]-=c;
diff[x2+1][y2+1]+=c;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)//由差分数组求原数组
a[i][j]=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+diff[i][j];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) cout<<a[i][j]<<" ";
cout<<endl;
}
return 0;
}