题意:给出一个n*m的矩阵,要求求出它所有r*c子矩阵里面的元素的最大值减最小值的差的最大值。
思路:二维的单调队列维护,时间复杂度为O(n^2)。
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
#define N 1005
int head,tail,mat[N][N],vmax[N][N],vmin[N][N]; //vmax[i][j]表示(i,j)到(i+d-1,j+d-1)中的最大值,vmin[i][j]表示(i,j)到(i+d-1,j+d-1)中的最小值。
struct node
{
int num,id;
};
node que[N];
void add_max(int num,int id)
{
while(head<tail&&que[tail-1].num<=num)tail--; //单调队列维护
que[tail].id=id;
que[tail++].num=num;
}
void add_min(int num,int id)
{
while(head<tail&&que[tail-1].num>=num)tail--;
que[tail].id=id;
que[tail++].num=num;
}
int get_num(int id)
{
while(head<tail&&que[head].id<id)head++;
return que[head].num;
}
int main()
{
//freopen("a.txt","r",stdin);
int n,m,r,c;
while(scanf("%d%d%d%d",&n,&m,&r,&c)!=EOF)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
scanf("%d",&mat[i][j]);
}
}
for(int i=0;i<m;i++)
{
head=tail=0;
for(int j=0;j<r-1;j++)add_max(mat[j][i],j);
for(int j=r-1;j<n;j++)
{
add_max(mat[j][i],j);
vmax[j-r+1][i]=get_num(j-r+1); //这时的vmax[j-r+1][i]表示第i列中的第j-r+1行到第j行的最大值
}
}
for(int i=0;i<=n-r;i++)
{
head=tail=0;
for(int j=0;j<c-1;j++)add_max(vmax[i][j],j); //这里就是二维单调队列维护了
for(int j=c-1;j<m;j++)
{
add_max(vmax[i][j],j);
vmax[i][j-c+1]=get_num(j-c+1);
}
}
for(int i=0;i<m;i++)
{
head=tail=0;
for(int j=0;j<r-1;j++)add_min(mat[j][i],j);
for(int j=r-1;j<n;j++)
{
add_min(mat[j][i],j);
vmin[j-r+1][i]=get_num(j-r+1);
}
}
for(int i=0;i<=n-r;i++)
{
head=tail=0;
for(int j=0;j<c-1;j++)add_min(vmin[i][j],j);
for(int j=c-1;j<m;j++)
{
add_min(vmin[i][j],j);
vmin[i][j-c+1]=get_num(j-c+1);
}
}
int ans=0;
for(int i=0;i<=n-r;i++)
{
for(int j=0;j<=m-c;j++)
{
ans=max(ans,vmax[i][j]-vmin[i][j]);
}
}
printf("%d\n",ans);
}
return 0;
}