bzoj1047-理想的正方形(二维单调队列)

题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值
解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处理
,用单调队列即可实现,再对整个矩阵进行枚举,再用一次单调队列。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int INF=1e9+7;
const int maxn=1002;
int row,col,N;
int A[maxn][maxn];
int Min[maxn][maxn],Max[maxn][maxn];
int q1[maxn],q2[maxn];
int f1,f2,r1,r2;
void init() //预处理
{
    for(int i=1;i<=row;i++)
    {
        f1=1,r1=0;
        f2=1,r2=0;
        for(int j=1;j<N;j++)
        {
            while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
            q1[++r1]=j;
            while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
            q2[++r2]=j;
        }
        for(int j=N;j<=col;j++)
        {
            while(r1>=f1&&A[i][q1[r1]]>=A[i][j]) r1--;
            q1[++r1]=j;
            while(q1[f1]+N<=j) f1++;
            Min[i][j-N+1]=A[i][q1[f1]]; //缩点后的最小值

            while(r2>=f2&&A[i][q2[r2]]<=A[i][j]) r2--;
            q2[++r2]=j;
            while(q2[f2]+N<=j) f2++;
            Max[i][j-N+1]=A[i][q2[f2]]; //缩点后的最大值
        }
    }
}
int solve()
{
    int ret=INF;
    for(int j=1;j+N-1<=col;j++) //对同一列进行枚举
    {
        f1=1,r1=0;
        f2=1,r2=0;
        int minv=INF,maxv=-INF;
        for(int i=1;i<N;i++)
        {
            while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
            q1[++r1]=i;
            while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
            q2[++r2]=i;
        }
        for(int i=N;i<=row;i++)
        {
            while(r1>=f1&&Min[q1[r1]][j]>=Min[i][j]) r1--;
            q1[++r1]=i;
            while(q1[f1]+N<=i) f1++;
            minv=Min[q1[f1]][j];
            while(r2>=f2&&Max[q2[r2]][j]<=Max[i][j]) r2--;
            q2[++r2]=i;
            while(q2[f2]+N<=i) f2++;
            maxv=Max[q2[f2]][j];
            ret=min(ret,maxv-minv);
        }
    }
    return ret;
}
int main()
{
    scanf("%d%d%d",&row,&col,&N);
    for(int i=1;i<=row;i++)
        for(int j=1;j<=col;j++) scanf("%d",&A[i][j]);
    init();
    printf("%d\n",solve());
    return 0;
}
View Code

 

posted @ 2016-08-26 10:49  wust_ouyangli  阅读(168)  评论(0编辑  收藏  举报