[BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】
生活随笔
收集整理的這篇文章主要介紹了
[BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目鏈接:BZOJ - 1047
?
題目分析
使用單調(diào)隊(duì)列在 O(n^2) 的時間內(nèi)求出每個 n * n 正方形的最大值,最小值。然后就可以直接統(tǒng)計(jì)答案了。
橫向有 a 個單調(diào)隊(duì)列(代碼中是 Q[1] 到 Q[a] ),維護(hù)每行當(dāng)前枚舉區(qū)間的單調(diào)隊(duì)列。
縱向一個單調(diào)隊(duì)列(代碼中是 Q[0] ),求出當(dāng)前枚舉區(qū)間的每行的單調(diào)隊(duì)列后,就得到了每行的這個區(qū)間的最小值(最大值),就相當(dāng)于一個長度為行數(shù)的數(shù)組,然后縱向做單調(diào)隊(duì)列,求出的就是正方形的最值了。
?
代碼
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath>using namespace std;const int MaxN = 1000 + 5, INF = 999999999;int a, b, n, Ans; int Map[MaxN][MaxN], Q[MaxN][MaxN], F[MaxN], Head[MaxN], Tail[MaxN], Min[MaxN][MaxN], Max[MaxN][MaxN]; //Q[0]是縱向的單調(diào)隊(duì)列 inline int gmin(int a, int b) {return a < b ? a : b;} inline int gmax(int a, int b) {return a > b ? a : b;}void Get_Min() {for (int i = 1; i <= a; ++i) {Head[i] = 1;Tail[i] = 0;}for (int i = 1; i <= b; ++i) {for (int j = 1; j <= a; ++j) {if (i > n && Head[j] <= Tail[j] && Q[j][Head[j]] == i - n) ++Head[j];while (Head[j] <= Tail[j] && Map[j][i] < Map[j][Q[j][Tail[j]]]) --Tail[j];Q[j][++Tail[j]] = i; } if (i >= n) {Head[0] = 1; Tail[0] = 0;for (int j = 1; j <= a; ++j){F[j] = Map[j][Q[j][Head[j]]];if (j > n && Head[0] <= Tail[0] && Q[0][Head[0]] == j - n) ++Head[0];while (Head[0] <= Tail[0] && F[j] < F[Q[0][Tail[0]]]) --Tail[0];Q[0][++Tail[0]] = j;if (j >= n) Min[j][i] = F[Q[0][Head[0]]]; }}} }void Get_Max() {for (int i = 1; i <= a; ++i) {Head[i] = 1;Tail[i] = 0;}for (int i = 1; i <= b; ++i) {for (int j = 1; j <= a; ++j) {if (i > n && Head[j] <= Tail[j] && Q[j][Head[j]] == i - n) ++Head[j];while (Head[j] <= Tail[j] && Map[j][i] > Map[j][Q[j][Tail[j]]]) --Tail[j];Q[j][++Tail[j]] = i; }if (i >= n) {Head[0] = 1; Tail[0] = 0;for (int j = 1; j <= a; ++j){F[j] = Map[j][Q[j][Head[j]]];if (j > n && Head[0] <= Tail[0] && Q[0][Head[0]] == j - n) ++Head[0];while (Head[0] <= Tail[0] && F[j] > F[Q[0][Tail[0]]]) --Tail[0];Q[0][++Tail[0]] = j;if (j >= n) Max[j][i] = F[Q[0][Head[0]]]; }}} }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", &Map[i][j]);Get_Min();Get_Max();Ans = INF;for (int i = n; i <= a; ++i) for (int j = n; j <= b; ++j) Ans = gmin(Ans, Max[i][j] - Min[i][j]);printf("%d\n", Ans);return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/JoeFan/p/4319732.html
總結(jié)
以上是生活随笔為你收集整理的[BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 3047 Zjnu Stadiu
- 下一篇: Oracle 表数据去重