一维前缀和
前缀和是一项很重要的预处理,可以大大降低算法的复杂度。我们可以理解为数组的前i项和.
给出数组a[1]、a[2]、a[3]…a[n].
设前缀和数组s[i]=a[1]+a[2]+…+a[i]
如果我们要算出a[3]+a[4]+…+a[15]的值,可以利用前缀和数组s[15]-s[3-1].
s[l,r]=s[r]-r[l-1].
void init(){
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
}
int get(int l,int r){
return sum[r]-sum[l-1];
}
二维前缀和
对于二维数组,前缀和数组sum[i][j]表示a[1…i][1…j]之和.也就是以所有点为右下角,(1,1)为左上角中的矩阵的和.
利用容斥原理
void init(){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j];
}
}
}
int get(int x1,int y1,int x2,int y2){
return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
}
一维差分
差分是一种和前缀和相对的策略
这种策略是b[i]=a[i]-a[i-1],b[1]=a[1].即相邻两数之差.b[i]的前缀和就是a[i]
a[1,2…,n]
b[i]=a[i]-a[i-1],b[1]=a[1].
差分数组可用于区间的修改和查询
void init(int l,int r,int num){
b[l]+=num,b[r+1]-=num;
}
int get(){
for(int i=1;i<=n;i++){
a[i]=a[i-1]+b[i];
}
}
二维差分
void init(int x1,int y1,int x2,int y2,int num){
b[x1][y1]+=num;
b[x1][y2+1]-=num;
b[x2+1][y1]-=num;
b[x2+1][y2+1]+=num;
}
void get(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
b[i][j]+=b[i][j-1]+b[i-1][j]-[i-1][j-1];
}
}
}