BZOJ1047: [HAOI2007]理想的正方形

【传送门:BZOJ1047


简要题意:

  给出a,b,n,给出一个a*b的矩阵,要求在这个矩阵中得到一个n*n的矩阵,使得这个n*n的矩阵的最大值-最小值的差最小,求出最小的差


题解:

  二维ST表(涨姿势)

  mx[i][j][k]表示左上角为(i-2k+1,j-2k+1),右下角为(i,j)的矩阵的最大值,mn[i][j][k]为最小值

  然后随便yy一下继承

  然后O(1)求最大最小值


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int mx[1100][1100][11],mn[1100][1100][11];
int bin[11],Log[1100];
int main()
{
    int a,b,n;
    scanf("%d%d%d",&a,&b,&n);
    Log[0]=-1;for(int i=1;i<=max(a,b);i++) Log[i]=Log[i/2]+1;
    bin[0]=1;for(int i=1;i<=10;i++) bin[i]=bin[i-1]<<1;
    memset(mx,0,sizeof(mx));memset(mn,63,sizeof(mn));
    for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) scanf("%d",&mx[i][j][0]),mn[i][j][0]=mx[i][j][0];
    for(int i=1;i<=a;i++)
    {
        for(int j=1;j<=b;j++)
        {
            for(int k=1;bin[k]<=min(i,j);k++)
            {
                mx[i][j][k]=max(mx[i][j][k-1],max(mx[i-bin[k-1]][j][k-1],max(mx[i][j-bin[k-1]][k-1],mx[i-bin[k-1]][j-bin[k-1]][k-1])));
                mn[i][j][k]=min(mn[i][j][k-1],min(mn[i-bin[k-1]][j][k-1],min(mn[i][j-bin[k-1]][k-1],mn[i-bin[k-1]][j-bin[k-1]][k-1])));
            }
        }
    }
    int ans=1<<31-1;
    for(int i=n;i<=a;i++)
    {
        for(int j=n;j<=b;j++)
        {
            int x=i-n+1,y=j-n+1;
            int k=Log[n];
            int mmax,mmin;
            mmax=max(mx[i][j][k],max(mx[x+bin[k]-1][j][k],max(mx[i][y+bin[k]-1][k],mx[x+bin[k]-1][y+bin[k]-1][k])));
            mmin=min(mn[i][j][k],min(mn[x+bin[k]-1][j][k],min(mn[i][y+bin[k]-1][k],mn[x+bin[k]-1][y+bin[k]-1][k])));
            ans=min(mmax-mmin,ans);
        }
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-04-25 10:43  Star_Feel  阅读(184)  评论(0编辑  收藏  举报