http://www.lydsy.com/JudgeOnline/problem.php?id=1047

 

先用单调队列求出每横着n个最大值

再在里面用单调队列求出每竖着n个的最大值

这样一个位置就代表了一个n*n矩阵的最大值

同理求出最小值

 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 1001

int num[N][N];

int mx1[N][N],mx2[N][N];
int mi1[N][N],mi2[N][N];

int q[N],pos[N],h,t;

void read(int &x)
{
    x=0; int f=1; char c=getchar();
    while(!isdigit(c)) { if(c=='-') f=-1; c=getchar();  }
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    x*=f;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("data.in","r",stdin);
        freopen("xxy.out","w",stdout);
    #endif
    int a,b,n;
    read(a); read(b); read(n);
    for(int i=1;i<=a;++i)
        for(int j=1;j<=b;++j)
            read(num[i][j]);
    for(int i=1;i<=a;++i)
    {
        h=t=0;
        for(int j=1;j<=b;++j) 
        {
            while(h<t && j-pos[h]+1>n) h++;
            while(h<t && num[i][j]>q[t-1]) t--;
            q[t]=num[i][j];
            pos[t++]=j;
            if(j>=n) mx1[i][j]=q[h];
        }
    }
    for(int j=n;j<=b;++j)
    {
        h=t=0;
        for(int i=1;i<=a;++i)
        {
            while(h<t && i-pos[h]+1>n) h++;
            while(h<t && mx1[i][j]>q[t-1]) t--;
            q[t]=mx1[i][j];
            pos[t++]=i;
            if(i>=n) mx2[i][j]=q[h];
        }
    }
    for(int i=1;i<=a;++i)
    {
        h=t=0;
        for(int j=1;j<=b;++j) 
        {
            while(h<t && j-pos[h]+1>n) h++;
            while(h<t && num[i][j]<q[t-1]) t--;
            q[t]=num[i][j];
            pos[t++]=j;
            if(j>=n) mi1[i][j]=q[h];
        }
    }
    for(int j=n;j<=b;++j)
    {
        h=t=0;
        for(int i=1;i<=a;++i)
        {
            while(h<t && i-pos[h]+1>n) h++;
            while(h<t && mi1[i][j]<q[t-1]) t--;
            q[t]=mi1[i][j];
            pos[t++]=i;
            if(i>=n) mi2[i][j]=q[h];
        }
    }
    int ans=2e9;
    for(int i=n;i<=a;++i)
        for(int j=n;j<=b;++j)
            ans=min(ans,mx2[i][j]-mi2[i][j]);
    printf("%d",ans);
}
AC

相关文章: