BZOJ1047 理想的正方形

这个题的数据感觉不强 , 可以考虑1e8级别的算法。(虽然最好的做法不必如此)

提示:
1. 如果按照最暴力的做法 , 很定是超时的 , 需要稍稍优化一下

我将在代码后继续解释:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <algorithm>

using namespace std;
const int maxn = 1100;
const int INF = 0x3f3f3f3f;

inline  int re() { int n; scanf("%d",&n); return n; }
int a , b , n;
int g[maxn][maxn];
int Min[maxn] , Max[maxn];

int qmin[maxn] , l1 , r1;
int qmax[maxn] , l2 , r2;

int main(int argc, char *argv[]) {

    a = re(); b = re(); n = re();

    for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) g[i][j] = re();

    int res = INF*2;
    for(int i=1;i+n-1<=a;i++)
    {
        l1 = r1 = 0;
        l2 = r2 = 0;        
        for(int j=1;j<=b;j++)
        {
            Min[j] = INF; Max[j] = -INF;
            for(int k=0;k<n;k++) 
                Min[j] = min(Min[j] , g[i+k][j]) , Max[j] = max(Max[j] , g[i+k][j]);

            if(l1<r1 && qmin[l1]==j-n) l1++;
            if(l2<r2 && qmax[l2]==j-n) l2++;
            while(l1<r1 && Min[qmin[r1-1]] >= Min[j]) r1--; qmin[r1++] = j;
            while(l2<r2 && Max[qmax[r2-1]] <= Max[j]) r2--; qmax[r2++] = j;

            if(j>=n) res = min(res , Max[qmax[l2]] - Min[qmin[l1]]);
        }
    }
    printf("%d\n",res);

    return 0;
}

我们尝试优化每一行的枚举。 把每一列抽象为一个Min , 一个Max , 这样两个单调队列就可以啦。

BTW: 代码还是很短的 , 如果喜欢用STL , 那几乎就没什么代码…… 因为常数很小 , 时间还是不错的=)

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