基础算法
前缀和
作用:
任意求一段范围内的值,o(1)的时间复杂度。
思路:
1、计算前缀和矩阵(容斥原理)
前缀和:S(x,y)= S(x-1,y)+S(x,y-1)+a(x,y)-S(x-1,y-1)
注意:数组下标为1
例如:21=17+10+2-8
2、在前缀和矩阵种求出子矩阵和
子矩阵和为A=S(x2,y2)-S(x2,y1-1)-S(x1-1,y2)+S(x1-1,y1-1)
例如6+2+1+2=26-6-10+1
练习题目
链接: 前缀和
差分
作用:
给原数组中间某一段连续区间加一个固定值,o(1)
原数组 :a1,a2,a3…
差分数组:
b1=a1
b2=a2-a1
b3=a3-a2
bn=an-a(n-1)
最后操作的原数组为:
a1=b1
a2=b1+b2
a3=b1+b2+b3
ai=b1+b2+b3+…+bi
伪代码
//给temp数组[L,R]区间加上C
int temp[N],b[N];
void insert(int l,int r,int c){
b[l]+=c;
b[r+1]-=c;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&temp[i]);
//初始化差分数组
insert(i,i,temp[i]);
}
while(m--){
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
insert(l,r,c);
}
//原数组
for(int i=1;i<=n;i++){
b[i]+=b[i-1];
cout<<b[i]<<" ";
}
练习题目
链接: 差分
二维差分
作用:给其中子矩阵加上一个值
求差分b(i,j)
b(x1,y1)+=C 相当于右下角正方形全部加C
b(x2+1,y1)-=C 相当于橘色部分的全部减去C
b(x1,y2+1)-=C 相当于白色部分全部减去C
b(x2+1,y2+1)+C,这个部分减去了2个C,实际只需要减去一个
求给元素在加C后:
对差分b,进行二维前缀求和
伪代码
int 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;
return 0;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
insert(i,j,i,j,a[i][j]);
}
while(q--){
int x1,y1,x2,y2,c;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
insert(x1,y1,x2,y2,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];
cout<<b[i][j]<<" ";
}
练习题目
链接: 二维差分