BZOJ 1047

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3686  Solved: 2037
[Submit][Status][Discuss]

Description

  有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。

Input

  第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

Output

  仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

Sample Input

5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

Sample Output

1
 
好久没写题了。。。
我可是要冲省队的呀!!!
 
这道题嘛就二维单调队列,理解起来并不难
先搞定一维的再加另一重循环应该能减少调试时间(可惜我没有意识到调了半天)
另外按列来看的时候要注意分清到底是哪一维再操作
 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define N 1005
using namespace std;
int a,b,n,lmax=1,rmax,lmin=1,rmin;
int m[N][N],qmax[N],qmin[N],tmax[N][N],tmin[N][N],amax[N][N],amin[N][N];
int main()
{
    scanf("%d%d%d",&a,&b,&n);
    for(int i=1;i<=a;i++)
        for(int j=1;j<=b;j++)
            scanf("%d",&m[i][j]);
    
    for(int i=1;i<=a;i++)
    {
        lmax=1;rmax=0;
        memset(qmax,0,sizeof(qmax));
        for(int j=1;j<=b;j++)
        {
            while(lmax<=rmax && qmax[lmax]<=j-n)lmax++;
            while(lmax<=rmax && m[i][j]>=m[i][qmax[rmax]])rmax--;
            qmax[++rmax]=j;tmax[i][j]=m[i][qmax[lmax]];
        }
        /*
        for(int k=1;k<=a;k++)printf("%d ",tmax[i][k]);
        printf("\n");
        */
        lmin=1;rmin=0;
        memset(qmin,0,sizeof(qmin));
        for(int j=1;j<=b;j++)
        {
            while(lmin<=rmin && qmin[lmin]<=j-n)lmin++;
            while(lmin<=rmin && m[i][j]<=m[i][qmin[rmin]])rmin--;
            qmin[++rmin]=j;tmin[i][j]=m[i][qmin[lmin]];
        }
    }
    /*
    printf("\n");
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=b;j++)
            printf("%d ",tmax[i][j]);
        printf("\n");
    }
    printf("\n");
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=b;j++)
            printf("%d ",tmin[i][j]);
        printf("\n");
    }
    */
    for(int i=1;i<=b;i++)
    {
        lmax=1;rmax=0;
        memset(qmax,0,sizeof(qmax));
        for(int j=1;j<=a;j++)
        {
            while(lmax<=rmax && qmax[lmax]<=j-n)lmax++;
            while(lmax<=rmax && tmax[j][i]>=tmax[qmax[rmax]][i])rmax--;
            qmax[++rmax]=j;amax[j][i]=tmax[qmax[lmax]][i];
        }
        /*
        for(int k=1;k<=a;k++)printf("%d ",amax[k][i]);
        printf("\n");
        */
        lmin=1;rmin=0;
        memset(qmin,0,sizeof(qmin));
        for(int j=1;j<=a;j++)
        {
            while(lmin<=rmin && qmin[lmin]<=j-n)lmin++;
            while(lmin<=rmin && tmin[j][i]<=tmin[qmin[rmin]][i])rmin--;
            qmin[++rmin]=j;amin[j][i]=tmin[qmin[lmin]][i];
        }
    }
    /*
    printf("\n");
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=b;j++)
            printf("%d ",amax[i][j]);
        printf("\n");
    }
    printf("\n");
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=b;j++)
            printf("%d ",amin[i][j]);
        printf("\n");
    }
    */
    int ans=1000000000;
    for(int i=n;i<=a;i++)
        for(int j=n;j<=b;j++)
            ans=min(ans,amax[i][j]-amin[i][j]);
    printf("%d",ans);
    
//    system("pause");
    return 0;
}

 

posted @ 2017-11-28 20:56  hyf20010101  阅读(132)  评论(0编辑  收藏  举报