一维前缀和
问题引入
数组arr= {1,2,3,4,5},问[2,4]的和
解决思想
定义前缀和数组sum={1,3,6,10,15};例如sum[1]=3,sum[4]=15;
[l,r]的和就等于 sum[r]-sum[l-1](当l>0时)
sum[r] (当l=0时)
如[2,4]的和等于sum[4]-sum[1]=12。
代码
#include<bits/stdc++.h>
using namespace std;
#define add(l,r) (l?sum[r]-sum[l-1]:sum[r]) //当l!=0时返回前者
int main()
{
int arr[5]={1,2,3,4,5};
int sum[5];
sum[0]=arr[0];
for(int i=1;i<5;i++)
sum[i]=sum[i-1]+arr[i];
cout<<add(2,4);
return 0;
}
一维差分
问题引入
数组arr={1,2,3,4,5},现在对 [0,2]-1,再对 [2,4]+3,问最终的数组
解决思想
arr 1 2 3 4 5
d 1 1 1 1 1 (arr后一位减去前一位)
sumd 1 2 3 4 5 (d的前缀和,会发现就等于arr)
那么对于[l,r]+v
首先 [l,r]+v 进行 d[l]+v,d[r+1]-v
然后 将得到的差分数组进行前缀和便得到答案
如题,得到差分数组为 0 1 4 2 1
答案为前缀和 0 1 5 7 8
代码
#include<bits/stdc++.h>
using namespace std;
int d[6]={0};//防止越界
void add(int l,int r,int v)
{
d[l]+=v;
d[r+1]-=v;
}
int main()
{
int arr[5]={1,2,3,4,5};
add(0,2,-1);
add(2,4,3);
for(int i=1;i<5;i++)
d[i]+=d[i-1];
for(int i=0;i<5;i++)
{
arr[i]+=d[i];
cout<<arr[i]<<" ";
}
memset(d,0,sizeof(0));//对d数组进行清零,便于下一次操作
return 0;
}
二维前缀和
问题引入
给定一个数组 {1,2,3,4} ,问(1,1)到(2,2)的和。 {5,6,7,8} {1,2,3,4}
解决思想
先解决(0,0)到(2,2)的和再减去多出来的部分
代码
#include<bits/stdc++.h>
using namespace std;
int arr[3][4]={{1,2,3,4},
{5,6,7,8},
{1,2,3,4}};
int sum[3][4];
void pre_sum(){
sum[0][0]=arr[0][0];
for(int j=1;j<4;j++)
sum[0][j]=sum[0][j-1]+arr[0][j];
for(int i=1;i<3;i++)
sum[i][0]=sum[i-1][0]+arr[i][0];
for(int i=1;i<3;i++)
{
for(int j=1;j<4;j++)
{
sum[i][j]=arr[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
}
}
}
int get_sum(int x1,int y1,int x2,int y2)
{
if(!x1&&!y1) return sum[x2][y2];
if(!x1)return sum[x2][y2]-sum[x2][y1-1];
if(!y1)return sum[x2][y2]-sum[x1-1][y2];
return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
}
int main()
{
pre_sum();
cout<<get_sum(1,1,2,2);
return 0;
}
二维差分
问题引入
已知数组 arr3={{1,2,3,4}, ,求(1,1)到(2,2)的部分加了1后的数组。 {1,2,3,4}, {1,2,3,4}}
解决思想
结合一维差分和前缀和。确定一个差分标记数组{0},对其中的一些关键点进行加减,再运用二维前缀和,这样就能得到在指定部分进行了加减的标记数组,在整体加上原数组即可。
代码
#include<bits/stdc++.h>
using namespace std;
int arr[3][4]={{1,2,3,4},
{1,2,3,4},
{1,2,3,4}};
int sum[3][4]={0},d[3][4]={0};
void add(int x1,int y1,int x2,int y2,int v)
{
d[x1][y1]+=v;
d[x1][y2+1]-=v;
d[x2+1][y1]-=v;
d[x2+1][y2+1]+=v;
}
void get_sum(){
sum[0][0]=d[0][0];
for(int j=1;j<4;j++)
sum[0][j]=sum[0][j-1]+d[0][j];
for(int i=1;i<3;i++)
sum[i][0]=sum[i-1][0]+d[i][0];
for(int i=1;i<3;i++)
{
for(int j=1;j<4;j++)
{
sum[i][j]=d[i][j]+sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
}
}
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
arr[i][j]+=sum[i][j];
}
}
}
void print()
{
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
add(1,1,2,2,1);
get_sum();
print();
return 0;
}
>W<