统计子矩阵
题目描述:
给定一个 N × M 的矩阵A,请你统计有多少个子矩阵(最小 1 × 1,最大 N × M) 满足:
子矩阵中所有数的和不超过给定的整数K?
输入格式:
第一行包含三个整数N, M 和K.
之后 N 行每行包含 M 个整数,代表矩阵A.
30%的测试数据:1≤N,M≤20;
70%的测试数据:1≤N,M≤100;
100%的测试数据:1≤N,M≤500;0≤Aij≤1000;1≤K≤250000000。
输出格式:
一个整数代表答案。
输入样例:
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
输出样例:
19
思路描述:前缀和+双指针
先确定上边界和下边界。在边界中将每个竖状的一列看做一个元素,利用双指针来求一段区间内的和不超过k的连续子区间的个数。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
ll a[505][505];
ll s[505][505];
int main()
{
ll n,m,k;
cin>>n>>m>>k;
for(ll i=1;i<=n;i++)
{
for(ll j=1;j<=m;j++)
{
cin>>a[i][j];
s[i][j]=s[i-1][j]+a[i][j];//只需要求每一列的前缀和即可
}
}
ll res=0;
ll sum=0;
for(ll i=1;i<=n;i++)
{
for(ll j=i;j<=n;j++)
{
sum=0;
for(ll l=1,r=1;l<=m&&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;
return 0;
}