P8783统计子矩阵题解
没瞅题面就瞎康题解的人(如某些抄题解的)往这里康:
题目传送门
题目大意
给定一个
30分蒟蒻之蒟蒻做法
首先,暴力这种万能(
80分蒟蒻做法
提到矩阵求和,我立马想到用二维前缀和(不会用前缀和的先康前缀和+差分+离散化+区间合并,题单 前缀和、差分与离散化和billbill。),枚举左上角和右下角求和,判断是否大于
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=666;
int n,m,k,h;
int a[N][N],s[N][N];
signed main(){
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lld",&a[i][j]);
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];//定义前缀和矩阵
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int l=1;l<=i;l++){
for(int r=1;r<=j;r++){//枚举左上角和右下角
if(s[i][j]-s[l-1][j]-s[i][r-1]+s[l-1][r-1]<=k){//符合条件,记录下来
h++;
}
}
}
}
}
printf("%lld",h);
return 0;
}
100分大佬做法
在80分的代码的基础上,我们只需进行亿点点优化,就能出现奇迹。方法是判断到一个矩阵和大于
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=666;
int n,m,k,h,a[N][N],s[N][N];
signed main() {
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
scanf("%lld",&a[i][j]);
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];//与80分代码相同
}
}
for(int i=1; i<=n; i++) {
for(int j=i; j<=n; j++) {
for(int l=1,r=1; r<=m; r++) {
while(l<=r&&s[j][r]-s[i-1][r]-s[j][l-1]+s[i-1][l-1]>k) {//判断是否符合矩阵的条件,并且矩阵和小于等于K
l++;
}
h+=r-l+1;//计入答案
}
}
}
printf("%lld",h);
return 0;
}