浙大集训day5:C

浙大集训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);
		}
	}
}
原文地址:https://www.cnblogs.com/zhanglichen/p/15548865.html