【BZOJ 1047】理想的正方形

来源:互联网 发布:中国移动网络投诉电话 编辑:程序博客网 时间:2024/05/29 08:32

题目来源:BZOJ 1047

思路:

用二维单调队列维护二维数组的最大值和最小值,之后直接查询。
具体的来说,先用单调队列维护每一行的值,再维护每一列的值。

代码:

#include <cstdio>#include <iostream>#include <algorithm>using namespace std;inline int gt(){    char c = ' ';    int num = 0, op = 1, ok = 0;    while(1){        c = getchar();        if(c == '-') op = -1;        if(c <= '9' && c >= '0') num = num * 10 + c  - '0', ok = 1;        else if(ok) return op * num;    }}int a1[1010][1010], a2[1010][1010], a3[1010][1010];int a4[1010][1010], a5[1010][1010];int a, b, n, res = 2e9;int q1[1010], l, r;int main(){    scanf("%d%d%d", &a, &b, &n);    for(int i = 1; i <= a; i ++)        for(int j = 1; j <= b; j ++)            a1[i][j] = gt();    for(int i = 1; i <= a; i ++){        l = 1, r = 0;        for(int j = 1; j <= b; j ++){            while(r >= l && j - q1[l] >= n) l ++;            while(r >= l && a1[i][j] >= a1[i][q1[r]]) r --;            q1[++r] = j;            a2[i][j] = a1[i][q1[l]];        }        l = 1, r = 0;        for(int j = 1; j <= b; j ++){            while(r >= l && j - q1[l] >= n) l ++;            while(r >= l && a1[i][j] <= a1[i][q1[r]]) r --;            q1[++r] = j;            a3[i][j] = a1[i][q1[l]];        }    }    for(int i = 1; i <= b; i ++){        l = 1, r = 0;        for(int j = 1; j <= a; j ++){            while(r >= l && j - q1[l] >= n) l ++;            while(r >= l && a2[j][i] >= a2[q1[r]][i]) r --;            q1[++r] = j;            a4[j][i] = a2[q1[l]][i];        }        l = 1, r = 0;        for(int j = 1; j <= a; j ++){            while(r >= l && j - q1[l] >= n) l ++;            while(r >= l && a3[j][i] <= a3[q1[r]][i]) r --;            q1[++r] = j;            a5[j][i] = a3[q1[l]][i];        }    }    for(int i = n; i <= a; i ++)        for(int j = n; j <= b; j ++)            if(a4[i][j] - a5[i][j] < res) res = a4[i][j] - a5[i][j];    printf("%d", res);    return 0;} 
0 0