1.前缀和
1.1一维前缀和
原数组a
前缀和数组s
公式:
前缀和可以快速求出一段区间的和
例题:
#include<iostream>
using namespace std;
const int N = 100005;
int n,m,arr[N],s[N];
int main()
{
cin >> n>>m;
for (int i = 1; i <=n; i ++ )
{
cin >> arr[i];
s[i]=s[i-1]+arr[i];//s[0]=0;
}
while (m -- )
{
int l,r;
cin>>l>>r;
cout << s[r]-s[l-1]<<endl;
}
}
1.2二维前缀和
原数组a,前缀和数组s
前缀和初始化: s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
减去s[i-1][j]+s[i-1][j]和s[i-1][j-1]重合部分(红色部分),然后加上a[i][j]
求(x1,y1),(x2,y2)的子矩阵的和
代码: 子矩阵的和:s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]
加上减多的一部分,因为s[x1-1][y1-1]被减了两次
例题:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N][N],s[N][N],n,m,q;
int main()
{
cin >> n>>m>>q;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
scanf("%d", &a[i][j]);//输入量较大,scanf效率更高
}
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);
cout << s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]<<endl;
}
}
2.差分
2.1一维差分
差分数组是每个元素与其前一个元素的差,可以用于让一个序列某一特定范围内的所有值都加上或减去一个常数。
diff[0]=0;//不写即可
for(int i=1;i<=n;i++)
diff[i]=a[i]-a[i-1];
//区间[l,r]中的所有值都加上常数c
diff[l] += c;
diff[r+1] -= c
例题:
#include<iostream>
using namespace std;
const int N = 1e6;
int arr[N],diff[N],n,m;
void fun(int l,int r,int c)
{
diff[l-1]+=c;
diff[r]-=c;
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
diff[0]=arr[0];
for (int i = 1; i < n; i ++ )
{
diff[i]=arr[i]-arr[i-1];
}
while (m -- )
{
int l,r,c;
cin>>l>>r>>c;
fun(l,r,c);
}
arr[0]=diff[0];
for(int i=1;i<n;i++)
{
arr[i]=arr[i-1]+diff[i];
}
for(int i=0;i<n;i++)
{
cout<<arr[i]<<" ";
}
}
2.2二维差分
二维差分初始化
diff[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
//差分矩阵计算出原数组的值
a[i][j]=diff[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
//简化写成
for (int i=1; i<=n; i++)
{
for (int j=1; j<=m; j++)
{
diff[i][j] += diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
printf("%d ", diff[i][j]);
}
}
在(x1,y1)到(x2,y2)的矩阵中加一个c
diff[x1][y1] += c;
diff[x1][y2+1] -=c;
diff[x2+1][y1] -=c;
diff[x2+1][y2+1] += c;
例题:
#include<iostream>
using namespace std;
const int N = 1010;
int a[N][N],diff[N][N];
int n,m,q;
int main()
{
cin>>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 ++ )
diff[i][j] = a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
while(q--)
{
int x1,y1,x2,y2,c;
scanf("%d%d%d%d%d",&x1,&y1,&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++)
{
diff[i][j] += diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
printf("%d ", diff[i][j]);
}
printf("\n");
}
return 0;
}