持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情
[蓝桥杯 2022 省 B] 统计子矩阵
题目描述
给定一个 的矩阵 ,请你统计有多少个子矩阵 (最小 , 最大 满足子矩阵中所有数的和不超过给定的整数 。
输入格式
第一行包含三个整数 和 。
之后 行每行包含 个整数, 代表矩阵 。
输出格式
一个整数代表答案。
样例 #1
样例输入 #1
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
样例输出 #1
19
提示
【样例说明】
满足条件的子矩阵一共有 ,包含:
大小为 的有 个。
大小为 的有 个。 大小为 的有 个。
大小为 的有 个。
大小为 的有 个。
【评测用例规模与约定】
对于 的数据, .
对于 的数据, .
对于 的数据, .
蓝桥杯 2022 省赛 B 组 F 题。
分析
说到这题真的是泪目了,第一次打蓝桥杯因为当时不会写二维前缀和,拿了个很丢人的省三(错失省二),痛定思痛,赛后就学习了二维前缀和,二位前缀和可以得70分,今天终于学会了满分做法(感谢y总),这题正解是用双指针加一维前缀和就ok啦,就是根据单调性,枚举行数,然后搞一下列的前缀和就ok了。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#define ll long long
#define AC return
#define Please 0
using namespace std;
const int N=510;
const int N2=5;
typedef pair<int,int>PII;
inline int read(){//快读
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
AC x*f;
}
int s[N][N];
int n,m,K;
int tag[N+5][N+5];
int main(){
cin>>n>>m>>K;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>s[i][j];
s[i][j]+=s[i-1][j];
}
}
ll res=0;
ll sum;
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
for(int l=1,r=1,sum=0;r<=m;r++){
sum+=s[j][r]-s[i-1][r];
while(sum>K){
sum-=s[j][l]-s[i-1][l];
l++;
}
res+=r-l+1;
}
}
}
cout<<res<<endl;
AC Please;
}
希望能帮助到大家()!