BZOJ1047 HAOI2007 理想的正方形

传送门
首先,我们应该先算出每一每N个数的最大值,保存在mx里面。
同样的再处理出mn(最小值)。
然后处理出mx数组中每一每N个数的最大值,保存在MX中。
同样的再处理出MN(最小值)。
(以上的处理用单调队列最方便。)
然后再n²处理出MX-MN的最小值就行了

这道题我的代码略丑……

/**************************************************************
    Problem: 1047
    User: geng4512
    Language: C++
    Result: Accepted
    Time:2284 ms
    Memory:20536 kb
****************************************************************/

#include<cstdio>
#define min(a,b) (a)<(b)?(a):(b)
const int MAXN = 1000 + 5;
int a, b, n, q[MAXN], mx[MAXN][MAXN], mp[MAXN][MAXN], mn[MAXN][MAXN], MX[MAXN][MAXN], MN[MAXN][MAXN];
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", &mp[i][j]);
    int l = 0, r = 0;
    for(int j = 1; j <= a; j ++) // 处理mx
    {
        l = 0, r = 0;
        for(int i = 1; i <= b; i ++)
        {
            while(l < r && mp[j][i] > mp[j][q[r-1]]) --r;
            while(l < r && q[l] <= i - n) ++l;
            q[r++] = i;
            mx[j][i] = mp[j][q[l]];
        }
    }
    l = 0, r = 0;
    for(int j = 1; j <= a; j ++)// 处理mn
    {
        l = 0, r = 0;
        for(int i = 1; i <= b; i ++)
        {
            while(l < r && mp[j][i] < mp[j][q[r-1]]) --r;
            while(l < r && q[l] <= i - n) ++l;
            q[r++] = i;
            mn[j][i] = mp[j][q[l]];
        }
    }
    l = 0, r = 0;
    for(int j = 1; j <= b; j ++) // 处理MX
    {
        l = 0, r = 0;
        for(int i = 1; i <= a; i ++)
        {
            while(l < r && mx[i][j] > mx[q[r-1]][j]) --r;
            while(l < r && q[l] <= i - n) ++l;
            q[r++] = i;
            MX[i][j] = mx[q[l]][j];
        }
    }
    l = 0, r = 0;
    for(int j = 1; j <= b; j ++) // 处理MN
    {
        l = 0, r = 0;
        for(int i = 1; i <= a; i ++)
        {
            while(l < r && mn[i][j] < mn[q[r-1]][j]) --r;
            while(l < r && q[l] <= i - n) ++l;
            q[r++] = i;
            MN[i][j] = mn[q[l]][j];
        }
    }
    int ans = 0x3f3f3f3f;
    for(int i = n; i <= a; i ++)
        for(int j = n; j <= b; j ++)
            ans = min(MX[i][j] - MN[i][j], ans);
    printf("%d\n", ans);
    return 0;
}

你可能感兴趣的:(单调队列,bzoj)