前缀和:指某个序列的前n项和
差分:前缀和的逆过程
当暴力超时,可考虑前缀和(废话
出现区间时说不定能排上用场,由前缀和方便计算区间和。
思路:区间[a,b]的区间和=s[b]-s[a-1]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[100005];
int s[100005]; //s[i]=a[1]+a[2]+a[3]+......a[i]
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
int m;
cin>>m;
while(m--)
{
int l,r;
cin>>l>>r;
int ans;
ans=s[r]-s[l-1];
cout<<ans<<endl;
}
return 0;
}
思路:这里需要用到二维前缀和
图片来源:A08 前缀和 二维前缀和_哔哩哔哩_bilibili
#include <bits/stdc++.h>
using namespace std;
int mp[5005][5005]; //二维前缀和
int main()
{
int n,r;
cin>>n>>r;
memset(mp,0,sizeof(mp));
for(int i=0;i<n;i++)
{
int x,y,v;
cin>>x>>y>>v;
mp[x+1][y+1]+=v;
}
for(int i=1;i<=5001;i++)
{
for(int j=1;j<=5001;j++)
{
mp[i][j]=mp[i][j]+mp[i-1][j]+mp[i][j-1]-mp[i-1][j-1];
}
}
int ans=0;
for(int i=r;i<=5001;i++)
{
for(int j=r;j<=5001;j++)
{
ans=max(ans,mp[i][j]-mp[i-r][j]-mp[i][j-r]+mp[i-r][j-r]);//mp[i][j]-mp[i-r][j]-mp[i][j-r]+mp[i-r][j-r]
} //代表边长为r的正方形
}
cout<<ans<<endl;
return 0;
}
5846:IncDec Sequence (tzcoder.cn)
思路:这题刚开始做时以为最少操作次数=给的数的最大值-最小值,错了,除非最大值和最小值在数组的头或尾,不然要以最大值,最小值为中点考虑左、右两个区间的情况。
用差分数组,则要使b[l+1,r]中都为0。
每次操作如果+1则b[l]+=1,b[r+1]-=1;如果-1则b[l]-=1,b[r+1]+=1
求让b[l+1,r]都为0的要进行几次操作,首先正负可以配对,然后让b[l+1,r]里面都为0,那么要变的只有b[r+1]
最后再改变b[r+1]和b[l],这两个是同时变的,这样求最终得到的数列可能有多少种。
例如
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int a[N];
int b[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
b[i]=a[i]-a[i-1];
LL r1=0;
LL r2=0;
for(int i=2;i<=n;i++)
{
if(b[i]>0)
r1+=b[i];
else
r2+=abs(b[i]);
}
LL ans;
ans=max(r1,r2); //min(r1,r2)+abs(r1-r2)=max(r1,r2)
cout<<ans<<endl;
cout<<abs(r1-r2)+1<<endl;
return 0;
}
这题是二维差分,需要逐行差分,然后求前缀和,知道改变[l,r]区间时同时改变a[l]和a[r+1]就可写出代码。
#include <bits/stdc++.h>
using namespace std;
int a[1005][1005]={0};
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
for(int j=x1;j<=x2;j++)
{
for(int k=y1;k<=y2;k++)
a[j][k]+=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(j>1)
cout<<" ";
cout<<a[i][j];
}
cout<<endl;
}
return 0;
}
部分代码思路参考了b站up主:董晓算法的个人空间-董晓算法个人主页-哔哩哔哩视频 (bilibili.com)