前缀和上课笔记(c++板子整理)
1.一维前缀和
#include<bits/stdc++.h>
using namespace std;
int a[1000010];
int n,t;//n是数组的大小,t是询问个数
int l,r;
int main(){
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++){
scanf("%d",a[i]);
a[i]+=a[i-1];//生成前缀和数组
}
while(t--){
scanf("%d%d",&l,&r);//输出l-r的区间和
printf("%d\n",a[r]-a[l-1]);//注意,l必须-1
}
return 0;
}
2.二维前缀和
#include<bits/stdc++.h>
using namespace std;
int n,m,t;
int a[1010][1010];
int s[1010][1010];
int main(){
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
while(t--){
int xa,ya,xb,yb;
scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
printf("%d\n",s[xb][yb]-s[xa-1][yb]-s[xb][ya-1]+s[xa-1][ya-1]);
}
return 0;
}
小福利
此处奉上题目上的题单题解
题单链接
第一题P8772 [蓝桥杯 2022 省 A] 求和
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200010];
int n,ans;
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
ans+=a[i]*a[i-1];
a[i]+=a[i-1];
}
printf("%lld",ans);
return 0;
}
第二题P6568 [NOI Online #3 提高组] 水壶
#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[1000010];
int mx;
int main(){
scanf("%d%d",&n,&k);
k++;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]+=a[i-1];
}
for(int i=k,j=0;i<=n;i++,j++){
mx=max(mx,a[i]-a[j]);
}
printf("%d",mx);
return 0;
}
第三题P2280 [HNOI2003] 激光炸弹
#include<bits/stdc++.h>
using namespace std;
int n,k;
int x,y,v;
int m[5005][5005],mx=-1;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&x,&y,&v);
m[x+1][y+1]=v;
}
for(int i=1;i<=5001;i++)
for(int j=1;j<=5001;j++)
m[i][j]=m[i][j-1]+m[i-1][j]-m[i-1][j-1]+m[i][j];
for(int i=k;i<=5001;i++)
for(int j=k;j<=5001;j++){
int ans=m[i][j]-m[i-k][j]-m[i][j-k]+m[i-k][j-k];
mx=max(ans,mx);
}
printf("%d",mx);
return 0;
}