浙大集训day5:C
给出一个\(n\times m\)的矩阵。
询问有多少个子矩阵,满足内部元素和<=k。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int _;
int n,m;
long long k;
int main () {
scanf("%d",&_);
while (_--) {
scanf("%d%d%lld",&n,&m,&k);
if (n>m) {
int a[m+2][n+2]={0};
long long c[m+2][n+2]={0};
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
scanf("%d",&a[j][i]);
}
}
swap(n,m);
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++) {
c[i][j]=c[i-1][j]+c[i][j-1]+a[i][j]-c[i-1][j-1];
}
}
long long ans=0;
for (int i=1;i<=n;i++) {
//枚举高度
for (int j=1;j<=n;j++) {
//枚举行
if (j+i-1>n) break;
int A=j,B=j+i-1;
int L=1,R=1;
long long sum=c[B][1]-c[A-1][1];
while (1) {
while (R<m&&sum+c[B][R+1]-c[B][R]-c[A-1][R+1]+c[A-1][R]<=k) {
sum+=c[B][R+1]-c[B][R]-c[A-1][R+1]+c[A-1][R];
R++;
}
if (sum<=k)ans+=R-L+1;
sum-=c[B][L]-c[B][L-1]-c[A-1][L]+c[A-1][L-1];
L++;
if (L>m) break;
}
}
}
printf("%lld\n",ans);
}
else {
int a[n+2][m+2]={0};
long long c[n+2][m+2]={0};
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++) {
c[i][j]=c[i-1][j]+c[i][j-1]+a[i][j]-c[i-1][j-1];
}
}
long long ans=0;
for (int i=1;i<=n;i++) {
//枚举高度
for (int j=1;j<=n;j++) {
//枚举行
if (j+i-1>n) break;
int A=j,B=j+i-1;
int L=1,R=1;
long long sum=c[B][1]-c[A-1][1];
while (1) {
while (R<m&&sum+c[B][R+1]-c[B][R]-c[A-1][R+1]+c[A-1][R]<=k) {
sum+=c[B][R+1]-c[B][R]-c[A-1][R+1]+c[A-1][R];
R++;
}
if (sum<=k)ans+=R-L+1;
sum-=c[B][L]-c[B][L-1]-c[A-1][L]+c[A-1][L-1];
L++;
if (L>m) break;
}
}
}
printf("%lld\n",ans);
}
}
}