欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 蓝桥杯 C++ b组 统计子矩阵深度解析

蓝桥杯 C++ b组 统计子矩阵深度解析

2025/3/10 12:47:41 来源:https://blog.csdn.net/yyp_5201314/article/details/146139737  浏览:    关键词:蓝桥杯 C++ b组 统计子矩阵深度解析

题目大意:给定一个 N×M 的矩阵 A,请你统计有多少个子矩阵 (最小1×1,最大N×M) 满足子矩阵中所有数的和不超过给定的整数 K?

前言:这题很容易想到二维前缀和优化,然后枚举子矩阵,但这样时间复杂度为O(N^{4}),而题中N最大500,大概就是1.25*10^{8},但我们一般要把操作次数维护到10^{7}~10^{8}之间为最佳!但这样以及能过70%的数据了QWQ

解题思路:(双指针+一位前缀和)
我们整体的优化思路是:枚举子矩阵的上下边界,这是双层循环,然后在每个固定的边界里,用左右指针l,r来查找状态下满足的子矩阵个数,这么说可能比较抽象,下面用通俗一些的话来解释吧!

1.首先,我们定义了上边界i,下边界j,可以理解为一个我们在找子矩阵的时候,我们先把它的上下给定住!比如上边界为1,下边界为N,那这个情况下其实就是原矩阵(N×M)的上边界和下边界。

2.但是!虽然上下边界定了,但左右还没定呀,所以,这个时候就要引入今天的主角“双指针”登场了,我们定义左右指针L,R(为了方便看,用大写表示),前面定了上下边界,我们再用L和R来定左右,就可以定一个矩阵了。(大脑里面应该能想想出来,不行的话用笔画一下)

3.题中要求的是子矩阵所有数的和<=K,而一开始L=R=1,我们是要遍历R到右端点,并且再这个过程中计算这个围成的矩阵和是否已经超过了K,超过了,那么就要让L++,并且对于每一个移动的R,应该都是可以固定一个L是其矩阵刚好<=K,那么此时L与R围成的矩阵的恰好满足 ,再次强调:我们这里是先定的R,然后对于每一个R都能找到一段恰好<=K的区间,然后这个LR围成的区间中,我们找的子区间是以R为有边界(因为我们是遍历的R),此时若以L右边的元素为左边界,比如L+1,那么也肯定满足,比如L=0,中间有个1,R=2,那么对于[L,R]区间,我们此次计入的子区间就是012,12,2;

4.关于一些计算的,就是利用一维前缀和,并不难理解,结合代码直接看应该更易理解,就不在这里阐述了,把第三条看明白基本此题的思路已经很明确了

#include<bits/stdc++.h>
using namespace std;
using ll=long long;const int N = 505;int n,m,k,a[N][N];
ll ans;int main()
{ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m>>k;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];a[i][j]+=a[i-1][j];//第j列的前缀和}}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+=a[j][r]-a[i-1][r];//j表示下边界,i表示上边界,r就是当前的列while(sum>k){sum-=a[j][l]-a[i-1][l]; l++; }ans+=r-l+1;}}}cout<<ans;return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词