一切都在潜移默化中ing
【问题引入】
给定n个数,再给出m个询问,每个询问给出区间(i,j)和x,要求 i 到 j 的每一个值都加上x,最后给出每一个询问区间(i,j)的区间和。
暴力:O(n^2);线段树或者树状数组O(logn);差分O(n);
下图为前缀和的定义式和递推式

什么是差分?差分是一个数组相邻两元素的差,一般为下标靠后的减去靠前的一个。设差分数组p[],即:
p[i] = a[i] - a[i - 1]
前缀和 和 差分 的联系
令F(a)表示前缀和数组,G(a)表示差分数组,则 F(G(a)) = G(F(a)) = a
前缀和 和 差分 是一对互逆过程。
根据上述表达式我们可以以O(1)求出区间[i,j]的区间和 sum(i,j) = a[j] - a[i-1]
通过一维前缀和可求得数组中前 i 个元素的和
b[ i ] [ j ] = b[ i - 1 ] [ j] +b[ j ] [ j - 1] -b[ i-1] [ j - 1] + a[ i ] [ j ]
#include<iostream>
#include<cstdlib>
using namespace std;
typedef long long ll;
ll m,n,a[100000],b[100000];
ll x,y;
int main()
{
cin>>n;
b[0] = 0;
for(ll i =1;i<=n;++i)
{
cin>>a[i];
b[i] = b[i-1]+a[i];
}
// for(int i =1;i<=n;++i)
// cout<<b[i]<<" ";
cout<<endl;
cin>>m;
while(m--)
{
cin>>x>>y;
printf("%lld\n",b[x+y-1]-b[x-1]);
}
system("pause");
return 0;
}#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int t;
int mp[1005][1004];
int b[1005][1005];
int n,m,x,y;
int main()
{
cin>>t;
while(t--)
{
memset(b,0,sizeof(b));
cin>>m>>n>>x>>y;
for(int i =1;i<=m;++i)
{
for(int j =1;j<=n;++j)
{
cin>>mp[i][j];
b[i][j] = b[i-1][j]+b[i][j-1]-b[i-1][j-1]+mp[i][j];
}
}
int ans=0;
for(int i =x;i<=m;++i)
{
for(int j =y;j<=n;++j)
{
ans=max(ans,b[i][j]-b[i-x][j]-b[i][j-y]+b[i-x][j-y]);
}
}
cout<<ans<<endl;
}
system("pause");
return 0;
}