题目链接
题目大意
给你一个nm的矩阵,找出所有ab的子矩阵的最小值,输出所有最小值之和
解题思路
这个题的思路还是挺巧妙的,首先我们先找出来每一行从j到j+b的最小值,存在c数组中,然后再在c数组中找出每一列i到i+a的最小值,就找出了每一个子矩阵的最小值了
找最小值的时候用单调队列的滑动窗口模拟一下就行
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=3005;
int g[N*N],e[N][N],c[N][N],d[N][N],q[N];
int main()
{
int n,m,a,b;
int g0,x,y,z;
scanf("%d %d %d %d",&n,&m,&a,&b);
scanf("%d %d %d %d",&g0,&x,&y,&z);
g[0]=g0;
for(int i=1; i<=n*m; i++)
g[i]=((long long)((long long)g[i-1]*(long long)x+(long long)y))%z;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{
e[i][j]=g[(i-1)*m+j-1];
//printf("%d\n",e[i][j]);
}
// for(int i=1; i<=n; i++)
// {
// for(int j=1; j<=m; j++)
// printf("%d ",e[i][j]);
// printf("\n");
// }
for(int i=1; i<=n; i++)
{
int s=1,t=1;
q[s]=0;
for(int j=1; j<=m; j++)
{
while(s<t&&e[i][q[t-1]]>=e[i][j])
t--;
q[t++]=j;
//printf("%d %d %d %d\n",i,j,t-1,q[t-1]);
if(j-b+1>=1)
{
// printf("%d %d\n",i,j-b+1);
c[i][j-b+1]=e[i][q[s]];
if(q[s]==j-b+1)
s++;
}
}
}
// printf("\n");
// for(int i=1; i<=n; i++)
// {
// for(int j=1; j<=m; j++)
// printf("%d ",c[i][j]);
// printf("\n");
// }
memset(q,0,sizeof(q));
memset(d,0,sizeof(d));
for(int i=1; i<=m; i++)
{
int s=1,t=1;
q[s]=0;
for(int j=1; j<=n; j++)
{
while(s<t&&c[q[t-1]][i]>=c[j][i])
t--;
q[t++]=j;
if(j-a+1>=1)
{
d[j-a+1][i]=c[q[s]][i];
if(q[s]==j-a+1)
s++;
}
}
}
// printf("\n");
// for(int i=1; i<=n; i++)
// {
// for(int j=1; j<=m; j++)
// printf("%d ",d[i][j]);
// printf("\n");
// }
long long ans=0;
for(int i=1; i<=(n-a+1); i++)
{
for(int j=1; j<=(m-b+1); j++)
ans+=(long long)d[i][j];
}
printf("%lld\n",ans);
return 0;
}