P2216 [HAOI2007]理想的正方形 [二維RMQ]
阿新 • • 發佈:2019-02-23
com 最值 int 參考文獻 -h main pan bits del
P2216 [HAOI2007]理想的正方形
這道題就是標準的二維RMQ模板。
回顧一下原來的RMQ,分兩個階段,先倍增的初始化,再\(O(1)\)地求答案。二維RMQ也是有異曲同工之妙的。
這個最值怎麽定義?我們設\(maxv[i][j][k]\)為以\((i,j)\)為左上角的\(2^k\times 2^k\)正方形區域中的最大值。最小值同理,下面都只討論最大值。
怎麽初始化?我們同樣枚舉\(k\)。一維RMQ通過枚舉\(k\)變成兩段,二維RMQ就會變成四個。都取最大值就是了。
怎麽求答案?同樣\(O(1)\)地算出\(n\)對應的\(k\),然後同樣取四個ST表得到最大值。
基本原理跟一維RMQ是完全一致的,唯一的不同就是需要討論4種,僅此而已。
好好看代碼8:
#include<bits/stdc++.h> const int maxn = 1002; const int INF = 0x3f3f3f3f; int maxv[12][maxn][maxn], minv[12][maxn][maxn]; int a, b, n; int ans = INF; 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", &maxv[0][i][j]); minv[0][i][j] = maxv[0][i][j]; } } for(int k = 1; (1 << k) <= n; k++) { for(int i = 1; i + (1 << k) - 1 <= a; i++) { for(int j = 1; j + (1 << k) - 1 <= b; j++) { maxv[k][i][j] = std::max(std::max(maxv[k - 1][i][j], maxv[k - 1][i + (1 << (k - 1))][j]), std::max(maxv[k - 1][i][j + (1 << (k - 1))], maxv[k - 1][i + (1 << (k - 1))][j + (1 << (k - 1))])); minv[k][i][j] = std::min(std::min(minv[k - 1][i][j], minv[k - 1][i + (1 << (k - 1))][j]), std::min(minv[k - 1][i][j + (1 << (k - 1))], minv[k - 1][i + (1 << (k - 1))][j + (1 << (k - 1))])); } } } int k = 0; while((1 << (k + 1)) <= n) k++; for(int i = 1; i + n - 1 <= a; i++) { for(int j = 1; j + n - 1 <= b; j++) { int max = std::max(std::max(maxv[k][i][j], maxv[k][i + n - (1 << k)][j]), std::max(maxv[k][i][j + n - (1 << k)], maxv[k][i + n - (1 << k)][j + n - (1 << k)])); int min = std::min(std::min(minv[k][i][j], minv[k][i + n - (1 << k)][j]), std::min(minv[k][i][j + n - (1 << k)], minv[k][i + n - (1 << k)][j + n - (1 << k)])); ans = std::min(ans, max - min); } } printf("%d\n", ans); }
參考文獻:https://www.cnblogs.com/GXZlegend/p/7491533.html
這篇博客的代碼真的漂亮。
漂亮警告
P2216 [HAOI2007]理想的正方形 [二維RMQ]